【问题标题】:Most efficient way to check if element exists in a set检查元素是否存在于集合中的最有效方法
【发布时间】:2017-08-04 07:10:45
【问题描述】:

所以在我的 MongoDB 数据库中,我有一个包含用户帖子的集合。

在该集合中,我有一个名为“likes”的集合,其中包含喜欢该帖子的用户的 ID 数组。查询时,我想将用户 ID 传递给我的查询,并在结果中有一个布尔值,告诉我该 ID 是否存在于数组中,以查看用户是否已经喜欢该帖子。我知道这很容易通过两个查询来完成,一个是获取帖子,另一个是检查用户是否喜欢它,但我想找到最有效的方法。

例如,我的一份文件是这样的

{
    _id: 24jef247jos991,
    post: "Test Post",
    likes: ["userid1", "userid2"]
}

当我从“userid1”查询时,我想要返回

{
    _id: 24jef247jos991,
    post: "Test Post",
    likes: ["userid1", "userid2"],
    userLiked: true
}

但是当我从“userid3”查询时,我想要

{
    _id: 24jef247jos991,
    post: "Test Post",
    likes: ["userid1", "userid2"],
    userLiked: false
}

【问题讨论】:

  • 不是重复的,这个问题提出了不同的问题。我了解如何不向集合添加重复项以及如何使用 addToSet 执行该操作。这更像是一个询问如何将两个查询的结果合二为一的问题。
  • 您查看已接受答案底部的编辑了吗?
  • @Veeram 是的,它建议您使用 findOne 运算符。我的问题是如何使用一个查询(例如聚合查询)来做到这一点。使用 findOne 将为结果中的每个帖子生成一个额外的查询。
  • 好的。取消链接。感谢您添加详细信息。

标签: node.js mongodb mongodb-query aggregation-framework


【解决方案1】:

您可以添加$addFields 阶段,根据输入用户检查每个文档likes 数组。

db.collection.aggregate( [
        {
           $addFields: {
              "userLiked":{ $in: [ "userid1", "$likes" ] }
           }
        }
] )

【讨论】:

  • 实际上由于某种原因我不得不使用 $in 运算符而不是 $eq,但总体思路可行。
  • 确实是这样。更新了答案。 $eq 聚合运算符的工作方式与 $eq 查询运算符略有不同。项目 / addFields 阶段的 $in 运算符支持最近才从 3.3.5 版本添加。感谢您的验证。这是相关票jira.mongodb.org/browse/SERVER-6146
【解决方案2】:

从 MongoDB 3.4 开始,您可以使用 $in 聚合运算符来检查数组是否包含给定元素。您可以使用 $addFields 运算符聚合运算符将新计算的值添加到文档中,而无需显式包含其他字段。

db.collection.aggregate( [
   { "$addFields": { "userLiked": { "$in": [ "userid1", "$likes" ] } } }
])

在 MongoDB 3.2 中,您可以使用 $setIsSubset 运算符和方括号 [] 运算符来执行此操作。这种方法的缺点是您需要手动$project 文档中的所有字段。此外,$setIsSubset 运算符可以对您的数组进行重复数据删除,这可能不是您想要的。

db.collection.aggregate([
    { "$project": { 
        "post": 1, "likes": 1, 
        "userLiked": { "$setIsSubset": [ [ "userid3" ], "$likes" ] } 
    }}
])

最后,如果您的 mongod 版本是 3.0 或更低版本,您需要使用 $literal 运算符而不是 [] 运算符。

【讨论】:

  • 谢谢,我的生产数据库实际上是 mongo 3.2,我最终通过过滤数组然后获取它的大小并检查大小是否 > 1 来解决这个问题,但这可能更有效
  • 另请注意,您接受的答案是错误的,因为$in 运算符中的第一个表达式应该是输入值。我不知道您如何使用新计算的字段,但您可以将 $filter$redact 结合使用,但请记住 $redact 会进行 collscan
  • @M.StyvaneSoukossi 感谢您对我的回答发表评论。修正了表达式的顺序。
猜你喜欢
  • 2023-02-04
  • 2021-05-05
  • 2010-11-23
  • 2021-08-24
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多