[英]Mongoose find documents by child criteria
我正在努力尋找在孩子身上具有特定屬性的所有文檔。 例如,我想找到所有孩子活動的用戶。
這些是我的模型
const userSchema = new mongoose.Schema({
child: {
type: mongoose.Schema.Types.ObjectId,
ref: 'child'
}
});
const childSchema = new mongoose.Schema({
active: {
type: Boolean,
default: true
}
});
我嘗試使用填充和匹配( .populate({path:'child', match: {active: true}})
),但如果不活動,我將所有具有子屬性的用戶都設為 null。 我只需要有活躍孩子的用戶。 我所有的研究都使用點語法,但出於某種原因,我得到了一個空數組。 見下文:
let usersWithActiveChild = await User.find({'child.active': true}));
console.log(usersWithActiveChild) // --> displays '[]'
謝謝你的幫助!
當您使用 ref 來引用另一個模式時,ZCCADCDEDB567ABAE643E15DCF0974E503Z 將文檔存儲在 MongoDB 中的單獨 collections 中。
存儲在用戶文檔的child
字段中的實際值是DBRef
。
如果您直接查看 MongoDB 中的數據,您會發現類似以下內容:
用戶集合
{
_id: ObjectId("5a934e000102030405000000")
child: DBRef("child",ObjectId("5a934e000102030405000001"),"DatabaseName")
}
兒童收藏:
{
_id: ObjectId("5a934e000102030405000001"),
active: true
}
當您填充用戶 object 時,Mongoose 獲取用戶文檔,然后獲取子文檔。 正如您所指出的,由於已經檢索到用戶文檔,因此populate
調用中的match
過濾了子項。
只有當孩子作為子文檔存儲在 MongoDB 中時,才能使用點分符號'child.active'
,例如
{
_id: ObjectId("5a934e000102030405000000")
child:{
_id: ObjectId("5a934e000102030405000001"),
active: true
}
}
但是您的孩子被定義為參考,因此情況並非如此。
為了根據引用子項的內容過濾用戶文檔列表,您需要
- 像您所做的那樣填充匹配,然后過濾結果集,或者
- 聚合用戶集合, 查找子文檔,然后匹配子字段。
這可以通過使用聚合框架輕松完成。
首先我們用$lookup加入兩個 collections 。 查找結果是數組,但是我們與 User 和 Child 的關系是一對一的,所以我們使用$arrayElemAt: ["$child", 0]
得到第一項。
最后,我們使用$match應用我們的過濾器"child.active": true,
。
let usersWithActiveChild = await User.aggregate([
{
$lookup: {
from: "childs", //must be PHYSICAL collection name
localField: "child",
foreignField: "_id",
as: "child",
},
},
{
$addFields: {
child: {
$arrayElemAt: ["$child", 0],
},
},
},
{
$match: {
"child.active": true,
},
},
]);
示例文檔:
db={
"users": [
{
"_id": ObjectId("5a834e000102030405000000"),
"child": ObjectId("5a934e000102030405000000")
},
{
"_id": ObjectId("5a834e000102030405000001"),
"child": ObjectId("5a934e000102030405000001")
},
{
"_id": ObjectId("5a834e000102030405000002"),
"child": ObjectId("5a934e000102030405000002")
},
],
"childs": [
{
"_id": ObjectId("5a934e000102030405000000"),
"active": true
},
{
"_id": ObjectId("5a934e000102030405000001"),
"active": false
},
{
"_id": ObjectId("5a934e000102030405000002"),
"active": true
}
]
}
Output:
[
{
"_id": ObjectId("5a834e000102030405000000"),
"child": {
"_id": ObjectId("5a934e000102030405000000"),
"active": true
}
},
{
"_id": ObjectId("5a834e000102030405000002"),
"child": {
"_id": ObjectId("5a934e000102030405000002"),
"active": true
}
}
]
或者作為一個更好的方法是首先獲得 activ child,然后像這樣查找用戶:
db.childs.aggregate([
{
$match: {
"active": true
}
},
{
$lookup: {
from: "users",
localField: "_id",
foreignField: "child",
as: "user"
}
}
])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.