2013-08-09 15 views
269

Jeśli mam ten schemat ...dokument znalezienia z tablicy, która zawiera określoną wartość

person = { 
    name : String, 
    favoriteFoods : Array 
} 

... gdzie tablica favoriteFoods jest wypełniona strun. Jak mogę znaleźć wszystkie osoby, które mają "sushi" jako swoje ulubione jedzenie za pomocą mangusty?

Miałem nadzieję na coś wzdłuż linii:

PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...}); 

(wiem, że nie ma $contains w MongoDB, po prostu wyjaśniając, co spodziewałem się znaleźć przed znając rozwiązanie)

Odpowiedz

401

As favouriteFoods jest prostą tablicę ciągów, można po prostu zapytać to pole bezpośrednio:

PersonModel.find({ favouriteFoods: "sushi" }, ...); 

Ale Chciałbym również polecić mA król tablica ciąg wyraźny w schemacie:

person = { 
    name : String, 
    favouriteFoods : [String] 
} 
+38

Przez tutaj jest dokumentacja: http://docs.mongodb.org/manual/tutorial/query-documents/#match-an-array-element –

+5

Działa to również, gdy 'favouriteFoods' jest: ' favouriteFoods: [{typ: Schema.Types.ObjectId, ref: 'Foo d '}] ' – ZzKr

+8

Jako ktoś nowy dla Mongo, pochodzący z RDBMS takiego jak MySQL, odkrycie, że takie rozwiązania działają tak prosto, bez konieczności łączenia się z JOIN i dodatkowymi tabelami, sprawia, że ​​zastanawiam się, dlaczego wcześniej nie zacząłem na Mongo. Ale to nie znaczy, że DBMS jest lepszy od drugiego - zależy to od twojego przypadku użycia. –

87

Nie ma $contains operator w MongoDB.

Możesz użyć odpowiedzi od JohnnyHK, ponieważ to działa. Najbliższą analogią zawiera że Mongo ma to $in, przy użyciu tej zapytanie będzie wyglądać następująco:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...); 
+9

Czy to prawda? Czy mongotb nie oczekuje tablicy wartości przy użyciu $ in? jak {name: {$ in: ["Paul", "Dave", "Larry", "Adam"]}}? –

+0

Przepraszam, masz rację, zaktualizowałem odpowiednio kod –

+13

Huh? To nie jest konieczne. '$ in' jest używane, gdy masz wiele wartości zapytania, a dokument musi być zgodny z jednym z nich. Na odwrót (o to właśnie chodzi w tym pytaniu), odpowiedź JohnnyHK jest poprawna. Miałem zamiar przegłosować, ale myślę, że ta odpowiedź może być pomocna dla innych osób, które znajdą się na tej stronie. – MalcolmOcean

-19

Znam ten temat jest stary, ale dla przyszłych ludzi, którzy mogliby więc dziwnego, że to samo pytanie, kolejna niezwykle nieefektywne rozwiązanie mogłoby być Zrobić:

PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'}); 

To pozwala uniknąć wszystkich optymalizacji przez MongoDB, więc nie używać w kodzie produkcyjnym.

+0

Z ciekawości, czy jest jakaś zaleta robienia tego w ten sposób? –

+38

W rzeczywistości jest to bardzo mało skuteczne ... – Crasher

+4

Jest to niezwykle nieskuteczne w porównaniu z zaakceptowaną odpowiedzią; omija całą optymalizację, którą Mongo umieszcza za kulisami dla znalezienia prostego, jak w zaakceptowanym. – unwitting

23

W przypadku trzeba znaleźć dokumenty, które zawierają NULL elementów wewnątrz tablicy dokumentów podrzędnych, Znalazłem tę kwerendę, która działa całkiem dobrze:

db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}}) 

To zapytanie jest pobierana z tego postu: MongoDb query array with null values

było to wspaniałe znalezisko i działa znacznie lepiej niż mój własny początkowy i źle wersji (który okazał się działać dobrze tylko dla tablic z jednego elementu):

.find({ 
    'MyArrayOfSubDocuments': { $not: { $size: 0 } }, 
    'MyArrayOfSubDocuments._id': { $exists: false } 
}) 
22

Czuję się jak $all byłby bardziej odpowiedni w tej sytuacji. Jeśli szukasz osoby, która jest w sushi zrobić:

PersonModel.find({ favoriteFood : { $all : ["sushi"] }, ...}) 

Jak można chcieć więcej filtrować wyszukiwania tak:

PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...}) 

$in to podoba, czy i $all jak AND.Sprawdź to: https://docs.mongodb.com/manual/reference/operator/query/all/

+0

Niestety, jest to niepoprawna odpowiedź na moje pytanie. Nie szukam dokładnego dopasowania, ale tylko dla tablic, które zawierają co najmniej określoną wartość. –

+6

To jest całkowicie poprawna odpowiedź na twoje pytanie! Dla jednej wartości nie ma różnicy w używaniu $ all lub $ in. Jeśli masz kilka wartości takich jak "sushi", "banany", $ all szuka osób, które mają "sushi" I "banany" w swojej tablicy ulubionych dań, jeśli używasz $ w tym, że dostajesz osoby, które mają "sushi" LUB "banany" "w ich ulubionej tablicy żywnościowej. – Jodo

12

w przypadku, tablica zawiera obiekty, na przykład jeśli favouriteFoods jest tablicą obiektów następuje:

{ 
    name: 'Sushi', 
    type: 'Japanese' 
} 

można użyć następującego zapytania:

PersonModel.find({"favouriteFoods.name": "Sushi"}); 
Powiązane problemy