it-swarm-id.com

Permintaan dokumen dengan ukuran array lebih besar dari 1

Saya memiliki koleksi MongoDB dengan dokumen dalam format berikut:

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

Saat ini saya bisa mendapatkan dokumen yang cocok dengan ukuran array tertentu: 

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

Ini dengan benar mengembalikan dokumen dengan 2 elemen dalam array name. Namun, saya tidak bisa melakukan perintah $gt untuk mengembalikan semua dokumen yang bidang name memiliki ukuran array lebih dari 2:

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

Bagaimana saya bisa memilih semua dokumen dengan array name dengan ukuran lebih besar dari satu (lebih disukai tanpa harus memodifikasi struktur data saat ini)?

522
emson

Ada cara yang lebih efisien untuk melakukan ini di MongoDB 2.2+ sekarang Anda dapat menggunakan indeks array numerik dalam kunci objek kueri.

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

Anda dapat mendukung permintaan ini dengan indeks yang menggunakan ekspresi filter parsial (membutuhkan 3,2+):

db.accommodations.createIndex(
    {'name.1': 1},
    {partialFilterExpression: {'name.1': {$exists: true}}}
);
1104
JohnnyHK

Saya percaya ini adalah permintaan tercepat yang menjawab pertanyaan Anda, karena itu tidak menggunakan klausa $where yang ditafsirkan:

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

Ini berarti "semua dokumen kecuali yang tanpa nama (baik array yang tidak ada atau kosong) atau hanya dengan satu nama."

Uji:

> 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" ] }
>
111
Tobia

Anda juga dapat menggunakan agregat:

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

// Anda menambahkan "size_of_name" ke transit dokumen dan menggunakannya untuk menyaring ukuran nama

46

Tak satu pun dari yang di atas bekerja untuk saya. Yang ini jadi saya bagikan:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )
33
Zloy Smiertniy

Coba lakukan sesuatu seperti ini:

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

1 adalah angka, jika Anda ingin mengambil catatan lebih dari 50 maka lakukan ArrayName.50.

30
Aman Goel
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
18
Yadvendar

Anda dapat menggunakan $ expr (operator versi 3,6 mongo) untuk menggunakan fungsi agregasi dalam kueri reguler. 

Bandingkan query operators vs aggregation comparison operators .

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
15
Veeram

Saya menemukan solusi ini, untuk menemukan item dengan bidang array yang lebih besar dari panjang tertentu

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

Agregat $ pertandingan pertama menggunakan argumen yang benar untuk semua dokumen. Jika kosong, saya akan mendapatkannya 

"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"
11
Barrard

MongoDB 3.6 termasuk $ expr https://docs.mongodb.com/manual/reference/operator/query/expr/

Anda dapat menggunakan $ expr untuk mengevaluasi ekspresi di dalam $ match, atau menemukan.

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

atau temukan

collection.find ({$ expr: {$ gte: [{$ size: "$ yourArrayField"}, 0]}});

0
Daniele Tassone