Zapytanie o dokumenty, w których rozmiar tablicy jest większy niż 1

Mam kolekcję MongoDB z dokumentami w następującym formacie:

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

Obecnie mogę uzyskać dokumenty, które pasują do określonego rozmiaru tablicy:

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

To poprawnie zwraca dokumenty z 2 elementami w tablicy name. Nie mogę jednak wykonać polecenia $gt, aby zwrócić wszystkie dokumenty, w których pole name ma rozmiar tablicy większy niż 2:

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

Jak mogę wybrać wszystkie dokumenty z tablicą name o rozmiarze większym niż jedna (najlepiej bez konieczności modyfikować bieżącą strukturę danych)?

Author: styvane, 2011-10-18

10 answers

Update:

dla wersji mongodb2.2+ bardziej efektywny sposób na to opisany przez @ JohnnyHK w innej Odpowiedzi.


1.Using $where

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

Javascript wykonuje się wolniej niż natywne operatory wymienione na ta strona, ale jest bardzo elastyczna. Zobacz stronę przetwarzania po stronie serwera więcej informacji.

2.Utwórz Dodatkowe pole NamesArrayLength, zaktualizuj je z nazwami długość tablicy, a następnie użyć w zapytaniach:

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

Będzie to lepsze rozwiązanie i będzie działać znacznie szybciej(można na nim utworzyć indeks).

 376
Author: Andrew Orsich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:36

W MongoDB 2.2+ jest na to bardziej efektywny sposób, ponieważ można używać indeksów tablic numerycznych w kluczach obiektów zapytania.

// Find all docs that have at least a second name array element.
db.accommodations.find({'name.1': {$exists: true}})
 1051
Author: JohnnyHK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-12 21:18:18

Uważam, że jest to najszybsze zapytanie, które odpowiada na twoje pytanie, ponieważ nie używa klauzuli zinterpretowanej $where:

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

Oznacza " wszystkie dokumenty oprócz tych bez nazwy (nieistniejących lub pustych tablic) lub z tylko jedną nazwą."

Test:

> 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" ] }
>
 109
Author: Tobia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-11 15:08:03

Możesz też użyć agregatu:

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

// dodajesz "size_of_name" do dokumentu tranzytowego i używasz go do filtrowania rozmiaru nazwy

 41
Author: one_cent_thought,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-23 19:00:06

Żadne z powyższych nie zadziałało. Ten zrobił więc się dzielę:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )
 30
Author: Zloy Smiertniy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-14 01:06:04

Spróbuj zrobić coś takiego:

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

1 jest liczbą, jeśli chcesz pobrać rekord większy niż 50, wykonaj ArrayName.50 Dzięki.

 28
Author: Aman Goel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 06:37:16
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
 16
Author: Yadvendar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 13:54:14

Znalazłem takie rozwiązanie, aby znaleźć elementy o polu tablicy większej niż pewna długość

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

Pierwszy agregat $match używa argumentu, który jest prawdziwy dla wszystkich dokumentów. If blank, I would get

"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"
 9
Author: Barrard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 01:46:59

Możesz użyć $expr ( operator wersji 3.6 mongo), aby używać funkcji agregujących w zwykłych zapytaniach.

Porównaj query operators vs aggregation comparison operators.

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
 8
Author: Veeram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 21:13:50

Chociaż powyższe odpowiedzi wszystkie działają, to co pierwotnie próbowałeś zrobić było poprawne, jednak po prostu masz składnię wstecz (Przełącz "$size " i "$gt")..

Poprawny:

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

Niepoprawne:

db.collection.find({items: {$size: {$gt: 1}}})
 -5
Author: Steffan Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-10 01:15:48