Aktualizace z roku 2017
$lookup nyní může přímo používat pole jako místní pole. $unwind
již není potřeba.
Stará odpověď
$lookup
fáze agregačního potrubí nebude pracovat přímo s polem. Hlavním záměrem návrhu je „levé spojení“ jako typ spojení „jedna k mnoha“ (nebo skutečně „vyhledání“) na možných souvisejících datech. Hodnota však má být singulární, nikoli pole.
Před provedením $lookup
proto musíte obsah nejprve "dennormalizovat". operaci, aby to fungovalo. A to znamená použít $unwind
:
db.orders.aggregate([
// Unwind the source
{ "$unwind": "$products" },
// Do the lookup matching
{ "$lookup": {
"from": "products",
"localField": "products",
"foreignField": "_id",
"as": "productObjects"
}},
// Unwind the result arrays ( likely one or none )
{ "$unwind": "$productObjects" },
// Group back to arrays
{ "$group": {
"_id": "$_id",
"products": { "$push": "$products" },
"productObjects": { "$push": "$productObjects" }
}}
])
Po $lookup
odpovídá každému členu pole, výsledkem je pole samotné, takže $unwind
znovu a $group
na $push
nová pole pro konečný výsledek.
Všimněte si, že všechny nalezené shody „levého spojení“, které nebudou nalezeny, vytvoří prázdné pole pro „productObjects“ na daném produktu, a tedy negují dokument pro prvek „product“ při druhém $unwind
se nazývá.
I když přímá aplikace na pole by byla hezká, v současnosti to funguje tak, že se singulární hodnota shoduje s možným mnoha.
Jako $lookup
je v zásadě velmi nový, v současnosti funguje tak, jak by ho znali ti, kteří znají mangusty jako "verze pro chudé muže" .populate()
metoda tam nabízená. Rozdíl je v tom, že $lookup
nabízí "serverové" zpracování "připojení" na rozdíl od klienta a určitou "vyspělost" v $lookup
aktuálně chybí to, co .populate()
nabídky (jako je interpolace vyhledávání přímo na poli).
Toto je ve skutečnosti přidělený problém pro vylepšení SERVER-22881, takže s trochou štěstí by se to objevilo v příštím vydání nebo brzy po něm.
Z principu návrhu není vaše současná struktura ani dobrá, ani špatná, ale pouze podléhá režii při vytváření jakéhokoli „spojení“. Jako takový platí základní princip MongoDB na počátku, kdy pokud „umíte“ žít s daty „předpřipojenými“ v jedné kolekci, pak je nejlepší to udělat.
Další věc, kterou lze říci o $lookup
Obecným principem je, že záměrem „připojení“ je fungovat opačně, než je zde uvedeno. Takže spíše než ponechání "souvisejících ID" ostatních dokumentů v "nadřazeném" dokumentu, obecný princip, který funguje nejlépe, je ten, kde "související dokumenty" obsahují odkaz na "nadřazený".
Takže $lookup
dá se říci, že „funguje nejlépe“ s „návrhem vztahů“, což je opak toho, jak něco jako mangusta .populate()
provádí připojení na straně klienta. Tím, že místo toho určíte „jeden“ v každém „mnoho“, pak jednoduše vtáhnete související položky, aniž byste museli $unwind
nejprve pole.