821

次の形式のドキュメントを含むMongoDBコレクションがあります。

{
  "_id" : ObjectId("4e8ae86d08101908e1000001"),
  "name" : ["Name"],
  "zipcode" : ["2223"]
}
{
  "_id" : ObjectId("4e8ae86d08101908e1000002"),
  "name" : ["Another ", "Name"],
  "zipcode" : ["2224"]
}

現在、特定の配列サイズに一致するドキュメントを取得できます。

db.accommodations.find({ name : { $size : 2 }})

nameこれにより、配列に2つの要素が含まれるドキュメントが正しく返されます。ただし、フィールドの配列サイズが2より大きい$gtすべてのドキュメントを返すコマンドを実行することはできません。name

db.accommodations.find({ name : { $size: { $gt : 1 } }})

nameサイズが1より大きいすべてのドキュメントを(できれば現在のデータ構造を変更せずに)選択するにはどうすればよいですか?

4

13 に答える 13

1591

クエリオブジェクトキーで数値配列インデックス(0ベース)を使用できるようになったため、MongoDB2.2以降でこれを行うためのより効率的な方法があります。

// Find all docs that have at least two name array elements.
db.accommodations.find({'name.1': {$exists: true}})

このクエリは、部分フィルター式を使用するインデックスでサポートできます(3.2以降が必要)。

// index for at least two name array elements
db.accommodations.createIndex(
    {'name.1': 1},
    {partialFilterExpression: {'name.1': {$exists: true}}}
);
于 2013-03-05T13:05:14.787 に答える
582

アップデート:

mongodbバージョン2.2以降の場合、これを行うためのより効率的な方法は、@JohnnyHKによって別の回答で説明されています。


1. $whereの使用

db.accommodations.find( { $where: "this.name.length > 1" } );

だが...

Javascriptは、このページにリストされているネイティブ演算子よりも実行速度が遅くなりますが、非常に柔軟性があります。詳細については、サーバー側の処理ページを参照してください。

2.追加のフィールドを作成NamesArrayLengthし、名前の配列の長さで更新してから、クエリで使用します。

db.accommodations.find({"NamesArrayLength": {$gt: 1} });

それはより良い解決策であり、はるかに速く動作します(それにインデックスを作成することができます)。

于 2011-10-18T17:27:17.710 に答える
157

インタプリタ$where句を使用しないため、これがあなたの質問に答える最速のクエリだと思います。

{$nor: [
    {name: {$exists: false}},
    {name: {$size: 0}},
    {name: {$size: 1}}
]}

これは、「名前のないドキュメント(存在しないか空の配列)または名前が1つしかないドキュメントを除くすべてのドキュメント」を意味します。

テスト:

> db.test.save({})
> db.test.save({name: []})
> db.test.save({name: ['George']})
> db.test.save({name: ['George', 'Raymond']})
> db.test.save({name: ['George', 'Raymond', 'Richard']})
> db.test.save({name: ['George', 'Raymond', 'Richard', 'Martin']})
> db.test.find({$nor: [{name: {$exists: false}}, {name: {$size: 0}}, {name: {$size: 1}}]})
{ "_id" : ObjectId("511907e3fb13145a3d2e225b"), "name" : [ "George", "Raymond" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225c"), "name" : [ "George", "Raymond", "Richard" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225d"), "name" : [ "George", "Raymond", "Richard", "Martin" ] }
>
于 2013-02-11T15:08:03.140 に答える
80

集約も使用できます。

db.accommodations.aggregate(
[
     {$project: {_id:1, name:1, zipcode:1, 
                 size_of_name: {$size: "$name"}
                }
     },
     {$match: {"size_of_name": {$gt: 1}}}
])

//トランジットドキュメントに「size_of_name」を追加し、それを使用して名前のサイズをフィルタリングします

于 2015-09-06T23:32:34.227 に答える
56

$ expr(3.6 mongoバージョン演算子)を使用して、通常のクエリで集計関数を使用できます。

query operators対を比較しaggregation comparison operatorsます。

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
于 2018-01-23T21:08:15.687 に答える
54

次のようなことを試してください。

db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})

1は数値です。50より大きいレコードをフェッチする場合は、ArrayName.50を実行してください。ありがとうございます。

于 2016-10-19T06:37:16.787 に答える
45

MongoDB3.6には$exprhttps ://docs.mongodb.com/manual/reference/operator/query/expr/が含まれています

$ exprを使用して、$ match内の式を評価したり、検索したりできます。

{ $match: {
           $expr: {$gt: [{$size: "$yourArrayField"}, 0]}
         }
}

または見つける

collection.find({$expr: {$gte: [{$size: "$yourArrayField"}, 0]}});
于 2019-01-30T13:37:49.023 に答える
41

上記のどれも私のために働いていませんでした。これはそうしましたので、私はそれを共有しています:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )
于 2014-05-14T01:06:04.963 に答える
27
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
于 2016-06-22T12:48:35.057 に答える
13

特定の長さを超える配列フィールドを持つアイテムを見つけるために、この解決策を見つけました

db.allusers.aggregate([
  {$match:{username:{$exists:true}}},
  {$project: { count: { $size:"$locations.lat" }}},
  {$match:{count:{$gt:20}}}
])

最初の$match集計は、すべてのドキュメントに当てはまる引数を使用します。空白の場合、私は取得します

"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"
于 2017-02-06T01:46:59.680 に答える
6

MongoDBアグリゲーションを使用して、次のタスクを実行できます。

db.collection.aggregate([
  {
    $addFields: {
      arrayLength: {$size: '$array'}
    },
  },
  {
    $match: {
      arrayLength: {$gt: 1}
    },
  },
])
于 2020-10-02T14:29:04.587 に答える
2

上記の答えはすべてうまくいきますが、最初にやろうとしたのは正しい方法でしたが、構文が逆になっているだけです(「$size」と「$gt」を切り替えてください)。

正しい:

db.collection.find({items: {$gt: {$size: 1}}})

正しくない:

db.collection.find({items: {$size: {$gt: 1}}})
于 2017-07-10T01:15:48.920 に答える
-2
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )

$gt$ltクエリで使用できます。

于 2020-08-26T19:18:28.400 に答える