繁体   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