簡體   English   中英

查詢依賴於mongodb中其他文檔的值的文檔

[英]query documents that depend on values of other documents in mongodb

想象以下貓鼬模型:

const UserSchema = Schema({
  //_id: ObjectId,
  //more fields,
  blockedIds: [{
    type: ObjectId,
    ref: 'User'
  }]
})

獲取與某個_id用戶的blockId不匹配的所有用戶的最有效方法是什么?

天真的方法是執行兩個查詢:

User.findById(id).then(user => {
  return User.find({_id: {$nin: user.blockedIds}})
})

是否可以使用聚合框架和$ facets在一個查詢中完成此操作?

嘗試從3.6開始使用不相關的子查詢作為您的用例。

就像是

User.aggregate(
 [{$lookup:{
   from: "users",
   pipeline:[
    {$match: {_id:mongoose.Types.ObjectId(id)}},
    {$project: {_id:0,blockedIds:1}}
   ],
   as: "noncr"
 }},
 {$match:{
   $expr:{
     $not:[
      {$in:[
        $_id,
        {$arrayElemAt:["$noncr.blockedIds",0]}
      ]}
    ]
  }
}},
{$project:{noncr:0}}]
)

$lookup提取輸入ID的“ blockedIds”,然后輸入$match過濾“ _id”不在blockedId列表中的文檔。

$expr允許在$ match階段使用聚合比較運算符。

$arrayElemAt從$ lookup數組中獲取第一個元素。

$in比較_id與blockedIds。

$project排除在外,以從最終響應中刪除“ noncr”字段。

請注意,當您測試查詢時,請在查找階段的“來自”屬性中使用集合名稱而不是模型名稱或架構名稱。

另一個答案中的聚合框架很有用,但是出於完整性考慮,這是另一種方法。 在Redis db設計中,您始終必須考慮從“雙向”訪問數據,因此您要考慮反轉結果。 這就是我們在這里可以做的。

而不是在用戶上使用blockedIds數組,而是使用blockedBy

const UserSchema = Schema({
  blockedBy: [{
    type: ObjectId,
    ref: 'User',
    index: true,
  }]
});

因此,現在您將問題反轉了,查詢變得無關緊要了:

User.find({ userID: { $nin: blockedBy: } });

在某些情況下,這可能是一個可行的選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM