我不確定這是一個真正的問題還是只是缺乏檔案。您可以將外部集合中檔案的條件放在查找中$match。您還可以將原始集合檔案的條件放在查找$match中$expr。
但是當我想同時使用這兩個功能時,它就不起作用了。這是聚合中的示例查找
{ $lookup:
{
from: 'books',
localField: 'itemId',
foreignField: '_id',
let: { "itemType": "$itemType" },
pipeline: [
{ $match: { $expr: { $eq: ["$$itemType", "book"] } }}
],
as: 'bookData'
}
}
$expr正在為原始檔案設定條件。但是,如果我只想獲取外國檔案status: 'OK'怎么辦?就像是:
{ $match: { status: "OK", $expr: { $eq: ["$$itemType", "book"] } }}
不作業。
uj5u.com熱心網友回復:
我試著玩你提供的情況。試著把它$expr作為$match物件的第一個鍵。它應該做的事情。
{ $lookup:
{
from: 'books',
localField: 'itemId',
foreignField: '_id',
let: { "itemType": "$itemType" },
pipeline: [
{ $match: { $expr: { $eq: ["$$itemType", "book"] }, status: 'OK' }}
],
as: 'bookData'
}
}
uj5u.com熱心網友回復:
當前接受的答案是“錯誤的”,因為它實際上并沒有改變任何東西。表示謂詞的欄位的順序$match沒有區別。我會用你的具體情況來證明這一點,但還有一個額外的復雜性,我們稍后會解決。同時,請考慮以下檔案:
{
_id: 1,
status: "OK",
key: 123
}
這個查詢:
db.collection.find({
status: "OK",
$expr: {
$eq: [
"$key",
123
]
}
})
而這個查詢,它只是將謂詞的順序顛倒了:
db.collection.find({
$expr: {
$eq: [
"$key",
123
]
},
status: "OK"
})
將找到并回傳該檔案。第一個的操場演示可以在這里找到,第二個在這里。
同樣,您的原件$match:
{ $match: { status: "OK", $expr: { $eq: ["$$itemType", "book"] } }}
將與接受的答案中的行為相同:
{ $match: { $expr: { $eq: ["$$itemType", "book"] }, status: 'OK' }}
換句話說,基于是否$expr首先使用,行為沒有區別。但是,我懷疑整體聚合并未表達您想要的邏輯。讓我們進一步探討一下。首先,我們需要解決這個問題:
$expr 為原始檔案設定條件。
這不是真的。根據檔案$expr,該運算子“允許在查詢語言中使用聚合運算式。 ”
此功能的主要用途(實際上是檔案中列出的第一個功能)是比較單個檔案中的兩個欄位。在 的背景關系中$lookup,這種從原始檔案中參考欄位的能力允許您將它們的值與您正在加入的集合進行比較。該檔案有一些示例,例如此處和該頁面上參考的其他位置$expr。
考慮到這一點,讓我們回到你的聚合。如果我理解正確,您對 { $expr: { $eq: ["$$itemType", "book"] }謂詞的意圖是從原始集合中過濾檔案。那正確嗎?
如果是這樣,那么這不是您的聚合當前正在做的事情。您可以在這個 Playground 示例中看到,$match嵌套的內部$lookup pipeline不會影響原始集合中的檔案。相反,您應該通過$matchbase 上的首字母進行過濾pipeline。所以是這樣的:
db.orders.aggregate([
{
$match: {
$expr: {
$eq: [
"$itemType",
"book"
]
}
}
}
])
或者,更簡單地說,這個:
db.orders.aggregate([
{
$match: {
"itemType": "book"
}
}
])
基于所有這些,您的最終管道應該類似于以下內容:
db.orders.aggregate([
{
$match: {
"itemType": "book"
}
},
{
$lookup: {
from: "books",
localField: "itemId",
foreignField: "_id",
let: {
"itemType": "$itemType"
},
pipeline: [
{
$match: {
status: "OK"
}
}
],
as: "bookData"
}
}
])
游樂場示例在這里。這個管道:
- 過濾原始集合 (
orders)中的資料itemType。從樣本資料中,它洗掉了檔案,_id: 3因為它itemType與我們正在尋找的檔案不同 ("book")。 - 它使用
localField/foreignField語法來查找檔案的 匹配集合中源檔案的books位置的_id資料。booksitemIdorders - 它進一步使用
let/pipeline語法來表示檔案status的附加條件是。這就是為什么帶有 的檔案不會被拉入帶有的檔案的原因。books"OK"booksstatus"BAD"bookDataorders_id: 2
(合并的)第二和第三部分的檔案在這里。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/531145.html
標籤:mongodb猫鼬
上一篇:MongoDBAggregation-如何只保留在外國集合中具有相關價值的檔案
下一篇:Mongoose開始和中止事務
