【问题标题】:How to find documents with exactly the same array entries as in a query如何查找与查询中的数组条目完全相同的文档
【发布时间】:2015-09-07 09:58:57
【问题描述】:

我在一个集合中有文档,如下所示:

[
  {
    userId: 1,
    itemsIds: [399957190, 366369952],
    hash: '85e765840b1cd3c413404cdf6b8fb2a4'
  },
  {
    userId: 2,
    itemsIds: [349551151, 366369952],
    hash: 'a28fa334515749b1b13fcd2183edb8de'
  },
  {
    userId: 3,
    itemsIds: [399957190, 366369952],
    hash: '85e765840b1cd3c413404cdf6b8fb2a4'
  }

]

这些是用户,他们的列表中有最喜欢的项目。我想要一个用户的列表给其他人,看看他们是否相等。如果是,我想在我的代码中将它们标记为一对并执行一些操作。

在上面的示例中,用户 1 和 3 拥有相同的收藏列表。 如何使用包含我列出的值的数组找到用户?

【问题讨论】:

  • MongoDB 本身(如果无模式),因此您不会在那里找到任何此类功能。您可以尝试使用 ODM(Object Document Mapper aka ORM for document)产品来处理这个问题,但它有自己的特点,即您需要所有驻留数据,以便在连接后创建“散列”结果。不是很明智。为了什么目的我可以问你是否认为这有必要?这里的真正目标是什么?请编辑您的问题以进行解释。长cmets是给像我这样的人问的。您的问题是详细信息,而不是 cmets。
  • 我们的目标是节省时间,而不必遍历整个数组并将其与我的搜索条件数组进行比较。有意义吗?
  • 不。一点意思都没有。也许如果您在“搜索”中解释了您“认为”您需要做什么,那么我们可以更好地告知您您真正“需要”什么。请编辑问题并解释。你“认为”你想要的答案是不切实际的。对于你真正“需要”的东西,我已经有了几个“猜测”。
  • 我希望 数据库索引 在这里会更有用?!见docs.mongodb.org/manual/reference/operator/query/eq/…
  • 我已经添加了更多细节,请看一下。

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


【解决方案1】:

这里有几个“非常有用的案例”,实际上试图在数组内容上创建一个“唯一哈希”实际上是“妨碍”了可以轻松解决的无数问题。

寻找“我”的共同点

例如,如果您从提供的示例中获取“用户 1”,并认为您已经加载了该数据,并希望通过匹配的“itemsIds”从当前用户对象中找到“与我共同的人” ,那么有两种简单的查询方式:

  1. 查找“完全相同”:是您要检查其他用户数据以查看具有相同“完全相同”兴趣的用户的位置。这是$all 查询运算符的简单且“无序”的用法:

    db.collection.find({ 
        "itemsIds": { "$all": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    这将返回“用户 3”,因为他们是具有“两个”公共“itemsIds”条目的用户。顺序在这里并不重要,因为它总是以任何顺序匹配,只要它们都在那里。这是$and 作为查询参数的另一种形式。

  2. 找到与我共同的“相似””:这基本上是在问“你有相同的东西吗?”。为此,你可以使用 @ 987654322@查询运算符,如果满足“任何一个”指定条件就会匹配:

    db.collection.find({ 
        "itemsIds": { "$in": [399957190, 366369952] },
        "userId": { "$ne": 1 }
    })
    

    在这种情况下,“用户 2”和“用户 3”“两者”都将匹配,因为它们“至少”共享“一个”指定条件,这意味着它们与查询的源数据。

    这实际上是$or 查询运算符的另一种形式,就像之前一样,根据要应用的条件,这种方式更简单明了。

寻找共同的“事物”

在某些情况下,您可能希望在没有基础“用户”的情况下找到“共同点”。那么如何判断“用户 1”和“用户 2”共享相同的“itemIds”,或者实际上不同的用户可能单独共享相同的“itemIds”值,但他们是谁?

  1. 获得完全匹配:当然是您同时查看“itemsIds”值和$group 它们。一般来说,这里的“订单很重要”,所以最好让它们“预先订购”,并且始终让它们变得简单:

    db.collection.aggregate([
        { "$group": {
            "_id": "$itemsIds",
            "common": { "$push": "$userId" }
        }}
    ])
    

    只要订单已经存在,这就是它的全部内容。如果没有,那么你可以做一个稍微长一点的形式来做“排序”,但同样可以说生成一个“哈希”:

    db.collection.aggregate([
        { "$unwind": "$itemsIds" },
        { "$sort": { "_id": 1, "itemsIds": 1 } },
        { "$group": {
            "_id": "$_id",
            "userId": { "$first": "$userId" },
            "itemsIds": { "$push": "$itemsIds" }
        }},
        { "$group": {
            "_id": "$itemsIds",
            "common": { "$push": "$userId" }
        }}
    ])
    

    不是“超级”性能,但它说明了为什么您总是在添加数组条目时保持有序。这是一个非常简单的过程。

  2. 普通的“用户”到“项目”:这是另一个简单的抽象过程,上面“分解”$unwind下的数组,然后基本上分组:

    db.collection.aggregate([
        { "$unwind": "$itemsIds" },
        { "$group": {
            "_id": "$itemsIds",
            "users": { "$addToSet": "$userId" }
        }}
    ])
    

    同样,只需一个简单的 $addToSet 分组聚合器就可以完成这项工作并为每个“itemsIds”值收集“不同的 userId”值。

这些都是基本解决方案,我可以继续“设置交叉点”等等,但这是“入门”。

不要试图计算“哈希”,MongoDB 有一个很好的“武器库”来匹配条目。使用它并“滥用它”,直到它坏掉。那就努力吧。

【讨论】:

  • 感谢您的全面回答!
猜你喜欢
  • 2017-07-21
  • 2017-09-20
  • 2023-03-17
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多