次の形式のドキュメントを含むMongoDBコレクションがあります。
{
"_id" : ObjectId("4e8ae86d08101908e1000001"),
"name" : ["Name"],
"zipcode" : ["2223"]
}
{
"_id" : ObjectId("4e8ae86d08101908e1000002"),
"name" : ["Another ", "Name"],
"zipcode" : ["2224"]
}
現在、特定の配列サイズに一致するドキュメントを入手できます。
db.accommodations.find({ name : { $size : 2 }})
これはname
配列に2つの要素を持つドキュメントを正しく返します。しかし、name
フィールドの配列サイズが2より大きいすべての文書を返すために$gt
コマンドを実行することはできません。
db.accommodations.find({ name : { $size: { $gt : 1 } }})
1より大きいサイズのname
配列を持つすべての文書を選択するにはどうすればよいですか(できれば現在のデータ構造を変更する必要なしに)。
更新:
mongodbバージョンの場合 2.2+ これを行うためのより効率的な方法は @JohnnyHK で別の answer で説明されています。
1. $ where を使う
db.accommodations.find( { $where: "this.name.length > 1" } );
しかし...
Javascriptはこのページにリストされているネイティブの演算子よりも実行が遅くなりますが、非常に柔軟です。詳しくは、サーバーサイドの処理ページを参照してください。
2. extra field NamesArrayLength
を作成し、それをnames配列の長さで更新してから、クエリで使用します。
db.accommodations.find({"NamesArrayLength": {$gt: 1} });
それはより良い解決策になるでしょう、そしてはるかに速く働くでしょう(あなたはそれにインデックスを作成することができます)。
MongoDB 2.2以降でこれを行うより効率的な方法があります。クエリオブジェクトキーで数値配列インデックスを使用できるようになりました。
// Find all docs that have at least a second name array element.
db.accommodations.find({'name.1': {$exists: true}})
このクエリは、部分フィルタ式を使用するインデックスでサポートできます(3.2以降が必要)。
db.accommodations.createIndex(
{'name.1': 1},
{partialFilterExpression: {'name.1': {$exists: true}}}
);
解釈された$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" ] }
>
あなたも集約を使用することができます:
db.accommodations.aggregate(
[
{$project: {_id:1, name:1, zipcode:1,
size_of_name: {$size: "$name"}
}
},
{$match: {"size_of_name": {$gt: 1}}}
])
//あなたはトランジットドキュメントに "size_of_name"を追加し、それを使って名前のサイズをフィルタリングします
上記のどれも私のために働きませんでした。これは私がそれを共有しているのでそうしました:
db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )
このようなことをしてみてください。
db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})
1が数値です。50を超えるレコードを取得する場合は、ArrayNameを実行してください。50ありがとう。
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
$ expr (3.6 mongo version operator)を使用して、通常のクエリで集計関数を使用できます。
query operators
vs aggregation comparison operators
を比較してください。
db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
私はこの解決法を見つけました、特定の長さより大きい配列フィールドを持つ項目を見つけるために
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"
MongoDB 3.6には$ expr https://docs.mongodb.com/manual/reference/operator/query/expr/ が含まれています。
$ matchの中の式を評価するために$ exprを使うことができます。
{$match: { $expr: {$gt: [{$size: "$yourArrayField"}, 0]} } }
または見つける
collection.find({$ expr:{$ gte:[{$ size: "$ yourArrayField"}、0]}});