如何查找与查询中具有完全相同数组条目的文档

How to find documents with exactly the same array entries as in a query

我在 collection 中有文档,看起来像这样:

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

]

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

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

这里有几个 "very useful cases" 实际上试图在数组内容上创建 "unique hash" 实际上是 "getting in the way" 可以轻松解决的无数问题。

寻找 "Me"

的共同点

例如,如果您从所提供的示例中获取 "user 1",并考虑到您已经加载了该数据,并且希望通过匹配的 "itemsIds" 从当前的内容中找到 "those in common with me" user对象有,那么有两种简单的查询方式:

  1. 找到"exactly"相同的:是你要检查其他用户数据的地方,看看那些有相同[=90=的用户】 利益。 $all 查询运算符的 "unordered" 用法很简单:

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

    return"user 3",因为它们是 "both" 常见的 "itemsIds" 条目。顺序在这里并不重要,因为它总是以任何顺序匹配,只要它们都在那里。这是 $and 作为查询参数的另一种形式。

  2. 找到我的共同点 "similar"": 这基本上是在问 "do you have something that is the same?"。为此,您可以使用 $in 查询运算符。如果满足指定条件的 "either",它将匹配:

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

    在这种情况下 "both" "user 2" 和 "user 3" 将匹配,因为它们 "at least" 共享 "one" 指定的条件,这意味着"something in common" 包含查询的源数据。

    这实际上是$or查询运算符的另一种形式,和以前一样,在给定要应用的条件下,这样写会更简单和简洁。

寻找共同点"Things"

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

  1. 获得完全匹配: 当然是您查看 "itemsIds" 值和 $group 值的地方。一般来说 "order is important" 在这里,所以最好你有它们 "pre-ordered" 并且始终如一地使它变得如此简单:

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

    这就是它真正的全部,只要订单已经存在。如果没有,那么你可以做一个稍微长一点的缠绕形式来做 "ordering",但同样可以说生成 "hash":

    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" }
        }}
    ])
    

    性能不"super",但它说明了为什么在添加数组条目时始终保持有序。这是一个非常简单的过程。

  2. Common "user" 到 "items": 这是另一个简单的过程,上面用 "breaking down" 下面的数组抽象$unwind,然后基本上分组回来:

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

    再一次,只是 $addToSet 的一个简单分组聚合器就可以完成这项工作,并为每个 "itemsIds" 值收集 "distinct userId" 值。

这些都是基本的解决方案,我可以继续 "set intersections" 什么不行,但这是 "primer".

不要尝试计算 "hash",MongoDB 有一个很好的 "arsenal" 来匹配条目。使用它和 "abuse it" 一样,直到它坏掉。那就更努力吧