web-dev-qa-db-ja.com

MongoDBの内部配列サイズのクエリ

usersコレクションのMongoDBドキュメントを考えてみましょう。

{ username : 'Alex', tags: ['C#', 'Java', 'C++'] }

サーバー側からtags配列の長さを取得する方法はありますか(タグをクライアントに渡さずに)?

ありがとうございました!

40
Zaur Nasibov

現在、MongoDB(2.6リリース) サポート$size集約の操作。

ドキュメントから:

{ <field>: { $size: <array> } }

あなたが望むものは、これを使用することで次のいずれかで達成できます:

db.users.aggregate(
   [
      {
         $group: {
            _id: "$username",
            tags_count:  {$first: {$size: "$tags" }}
         }
      }
   ]
)

または

db.users.aggregate(
   [
      {
         $project: {
            tags_count: {$size: "$tags"}
         }
      }
   ]
)
16
anvarik

ユーザー名Alexが一意の場合、次のコードを使用できます。

db.test.insert({username:"Alex", tags: ['C#', 'Java', 'C++'] });
db.test.aggregate(
  {$match: {username : "Alex"}}, 
  {$unwind: "$tags"},
  {$project: {count:{$add:1}}},
  {$group: {_id: null, number: {$sum: "$count" }}}
);
{ "result" : [ { "_id" : null, "number" : 3 } ], "ok" : 1 }
29
xmm.dev

$ inc を使用して、またはスケジュールのジョブを使用して、(個別のフィールドとして)各保存のタグの数を計算する方が効率的であると思います。

Map/reduceを使用してこれを行うこともできます( 標準的な例 )が、それは望んでいることではないようです。

あなたが尋ねていることを正確に行うことができるかどうかはわかりませんが、特定のサイズに一致するすべてのドキュメントを $ size で照会できます...

> db.collection.find({ tags : { $size: 3 }});

これで、3つのタグを持つすべてのドキュメントが取得されます...

16
Justin Jenkins

xmm.devの答えは単純化できます:中間フィールド 'count'の代わりに、$ groupで直接合計できます:

db.test.aggregate(
  {$match: {username : "Alex"}}, 
  {$unwind: "$tags"},
  {$group: {_id: null, number: {$sum: 1 }}}
) 
10

現在、それを行う唯一の方法はdb.evalが、これは 他の操作のためにデータベースをロックする

最も効率的な方法は、配列の長さを格納する追加フ​​ィールドを追加し、 $ inc および $ Push 操作で維持することです。

9
plaes

配列サイズを照会し、0より大きいが1〜3のいずれかである可能性がある場合に返す必要があるため、小さな回避策を行いました。

ここに私の解決策がありました:

db.test.find($or : [{$field : { $exists : true, $size : 1}},
                    {$field : { $exists : true, $size : 2}},
                    {$field : { $exists : true, $size : 3}}, ])

これは基本的に、属性が存在し、サイズが1、2、または3の場合にドキュメントを返します。ユーザーは、特定のサイズまたは範囲内を探している場合、ステートメントを追加して増分できます。私はそれが完璧ではないことを知っていますが、うまくいき、比較的迅速でした。属性に1〜3のサイズしかないため、このソリューションは機能しました。

0
kwoodson