Pobiera tylko element zapytany w tablicy obiektów w kolekcji MongoDB
Załóżmy, że masz następujące dokumenty w mojej kolekcji:
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":"circle",
"color":"green"
}
]
}
Do zapytania:
db.test.find({"shapes.color": "red"}, {"shapes.color": 1})
Lub
db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})
Zwraca dopasowany dokument (dokument 1), Ale zawsze ze wszystkimi elementami tablicy w shapes
:
{ "shapes":
[
{"shape": "square", "color": "blue"},
{"shape": "circle", "color": "red"}
]
}
Jednak chciałbym uzyskać dokument (dokument 1) tylko z tablicą zawierającą color=red
:
{ "shapes":
[
{"shape": "circle", "color": "red"}
]
}
Jak mogę to zrobić? 10 answers
MongoDB 2.2 nowy $elemMatch
Operator projekcji zapewnia inny sposób zmiany zwracanego dokumentu tak, aby zawierał tylko pierwszy dopasowany shapes
element:
db.test.find(
{"shapes.color": "red"},
{_id: 0, shapes: {$elemMatch: {color: "red"}}});
Zwraca:
{"shapes" : [{"shape": "circle", "color": "red"}]}
W 2.2 można to również zrobić za pomocą $ projection operator
, gdzie $
w polu Nazwa obiektu projekcji reprezentuje indeks pierwszego pasującego elementu tablicy z zapytania. Poniższe wyniki zwracają te same wyniki Co powyżej:
db.test.find({"shapes.color": "red"}, {_id: 0, 'shapes.$': 1});
MongoDB 3.2 Update
Począwszy od wydania 3.2, możesz użyć nowego $filter
operator agregacji do filtrowania tablicy podczas projekcji, który ma tę zaletę, że zawiera wszystkie dopasowania, zamiast tylko pierwszego.
db.test.aggregate([
// Get just the docs that contain a shapes element where color is 'red'
{$match: {'shapes.color': 'red'}},
{$project: {
shapes: {$filter: {
input: '$shapes',
as: 'shape',
cond: {$eq: ['$$shape.color', 'red']}
}},
_id: 0
}}
])
Wyniki:
[
{
"shapes" : [
{
"shape" : "circle",
"color" : "red"
}
]
}
]
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-09-25 18:04:43
Nowy Framework agregacji W MongoDB 2.2+ stanowi alternatywę dla Map/Reduce. Na $unwind
operator może być użyty do oddzielenia tablicy shapes
W Strumień dokumentów, który można dopasować:
db.test.aggregate(
// Start with a $match pipeline which can take advantage of an index and limit documents processed
{ $match : {
"shapes.color": "red"
}},
{ $unwind : "$shapes" },
{ $match : {
"shapes.color": "red"
}}
)
Wyniki w:
{
"result" : [
{
"_id" : ObjectId("504425059b7c9fa7ec92beec"),
"shapes" : {
"shape" : "circle",
"color" : "red"
}
}
],
"ok" : 1
}
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-01-28 08:41:36
Uwaga: Ta odpowiedź dostarcza rozwiązania, które było istotne w tym czasie, zanim wprowadzono nowe funkcje MongoDB 2.2 i up. Zobacz inne odpowiedzi, jeśli używasz nowszej wersji MongoDB.
Parametr wyboru pola jest ograniczony do pełnych właściwości. Nie można go użyć do wybrania części tablicy, tylko całej tablicy. Próbowałem użyć $ operator pozycyjny , ale to nie zadziałało.
Najprostszym sposobem jest aby po prostu filtrować kształty w kliencie .
Jeśli naprawdę potrzebujesz poprawnego wyjścia bezpośrednio z MongoDB, możesz użyć Map-reduce do filtrowania kształtów.
function map() {
filteredShapes = [];
this.shapes.forEach(function (s) {
if (s.color === "red") {
filteredShapes.push(s);
}
});
emit(this._id, { shapes: filteredShapes });
}
function reduce(key, values) {
return values[0];
}
res = db.test.mapReduce(map, reduce, { query: { "shapes.color": "red" } })
db[res.result].find()
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-07-19 18:42:45
Innym interesującym sposobem jest użycie $redact, która jest jedną z nowych funkcji agregacji MongoDB 2.6 . Jeśli używasz 2.6, nie potrzebujesz $unwind, który może powodować problemy z wydajnością, jeśli masz duże tablice.
db.test.aggregate([
{ $match: {
shapes: { $elemMatch: {color: "red"} }
}},
{ $redact : {
$cond: {
if: { $or : [{ $eq: ["$color","red"] }, { $not : "$color" }]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}}]);
$redact
"ogranicza treść dokumentów na podstawie informacji przechowywanych w samych dokumentach" . Więc będzie działać tylko wewnątrz dokumentu . Zasadniczo skanuje twój dokument do na dole i sprawdza, czy pasuje do twojego if
warunku, który jest w $cond
, jeśli jest dopasowanie, zatrzyma zawartość($$DESCEND
) lub usunie ($$PRUNE
).
W powyższym przykładzie, first $match
zwraca całą tablicę shapes
, a $redact usuwa ją do oczekiwanego wyniku.
Zauważ, że {$not:"$color"}
jest konieczne, ponieważ skanuje również górny dokument, a jeśli $redact
nie znajdzie pola color
na górnym poziomie, to zwróci false
, które może pozbawić cały dokument czego nie chcemy.
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-06-04 08:31:35
Lepiej można odpytywać w pasującym elemencie tablicy używając {[1] } czy jest pomocne zwrócenie znaczącego obiektu w tablicy.
db.test.find({"shapes.color" : "blue"}, {"shapes.$" : 1})
$slice
jest pomocny, gdy znasz indeks elementu, ale czasami chcesz
niezależnie od tego, który element tablicy odpowiada twoim kryteriom. Możesz zwrócić pasujący element
z operatorem $
.
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-09-18 09:14:37
Składnia find w mongodb to
db.<collection name>.find(query, projection);
I drugie zapytanie, które napisałeś, to jest
db.test.find(
{shapes: {"$elemMatch": {color: "red"}}},
{"shapes.color":1})
W tej części użyłeś operatora $elemMatch
w części zapytania, podczas gdy jeśli użyjesz tego operatora w części projekcji, otrzymasz pożądany rezultat. Możesz zapisać swoje zapytanie jako
db.users.find(
{"shapes.color":"red"},
{_id:0, shapes: {$elemMatch : {color: "red"}}})
To da Ci pożądany rezultat.
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-01-31 08:19:11
db.getCollection('aj').find({"shapes.color":"red"},{"shapes.$":1})
wyjścia
{
"shapes" : [
{
"shape" : "circle",
"color" : "red"
}
]
}
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-12-07 06:25:02
Dzięki JohnnyHK.
Tutaj chcę tylko dodać trochę bardziej skomplikowanego użycia.
// Document
{
"_id" : 1
"shapes" : [
{"shape" : "square", "color" : "red"},
{"shape" : "circle", "color" : "green"}
]
}
{
"_id" : 2
"shapes" : [
{"shape" : "square", "color" : "red"},
{"shape" : "circle", "color" : "green"}
]
}
// The Query
db.contents.find({
"_id" : ObjectId(1),
"shapes.color":"red"
},{
"_id": 0,
"shapes" :{
"$elemMatch":{
"color" : "red"
}
}
})
//And the Result
{"shapes":[
{
"shape" : "square",
"color" : "red"
}
]}
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 11:54:50
Wystarczy uruchomić zapytanie
db.test.find(
{"shapes.color": "red"},
{shapes: {$elemMatch: {color: "red"}}});
Wyjście tego zapytania to
{
"_id" : ObjectId("562e7c594c12942f08fe4192"),
"shapes" : [
{"shape" : "circle", "color" : "red"}
]
}
Zgodnie z oczekiwaniami wyświetli dokładne pole z tablicy pasujące do koloru: 'red'.
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-11-10 07:50:37
Wraz z $project będzie bardziej odpowiednie inne mądre pasujące elementy będą łączone razem z innymi elementami w dokumencie.
db.test.aggregate(
{ "$unwind" : "$shapes" },
{ "$match" : {
"shapes.color": "red"
}},
{"$project":{
"_id":1,
"item":1
}}
)
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-09 15:45:13