MongoDB获取需要与同一集合中的其他文档进行比较的唯一文档

MongoDB获取需要与同一集合中的其他文档进行比较的唯一文档,mongodb,mongodb-query,Mongodb,Mongodb Query,下面是我在测试集合中的示例文档结构 问题描述: 我必须根据以下条件从本文档中获取名称字段 我将通过角色字段作为查询条件。它应该获取与文档中的角色无关的名称值 请考虑下面的文档。如果我的查询标准是“角色 R1 < /Cord>”,则“查找查询”应将名称返回为: {“name”:“S”},{“name”:“G”},{“name”:“H”} 因为在集合中的任何文档中,r1未分配给此名称 同样的规则适用于所有角色,如r2,r3…r7。 因此,基本上我们必须查找集合中的所有文档,并且需要获取未分配给任何组

下面是我在测试集合中的示例文档结构

问题描述:

我必须根据以下条件从本文档中获取
名称
字段

我将通过
角色
字段作为查询条件。它应该获取与文档中的
角色
无关的
名称

请考虑下面的文档。如果我的查询标准是“角色<代码> R1 < /Cord>”,则“查找查询”应将名称返回为:

{“name”:“S”},{“name”:“G”},{“name”:“H”}

因为在集合中的任何文档中,
r1
未分配给此名称

同样的规则适用于所有角色,如
r2
r3
r7
。 因此,基本上我们必须查找集合中的所有文档,并且需要获取未分配给任何组的名称

/* 0 */
    {
        "_id" : ObjectId("567286bda5543ad892916a49"),
        "name" : "A",
        "role" : "r1"
    }

    /* 1 */
    {
        "_id" : ObjectId("567286bda5543ad892916a4a"),
        "name" : "A",
        "role" : "r2"
    }

    /* 2 */
    {
        "_id" : ObjectId("567286bda5543ad892916a4b"),
        "name" : "A",
        "role" : "r3"
    }

    /* 3 */
    {
        "_id" : ObjectId("567286bda5543ad892916a4c"),
        "name" : "B",
        "role" : "r2"
    }

    /* 4 */
    {
        "_id" : ObjectId("567286bda5543ad892916a4d"),
        "name" : "A",
        "role" : "r4"
    }

    /* 5 */
    {
        "_id" : ObjectId("567286bda5543ad892916a4e"),
        "name" : "B",
        "role" : "r1"
    }

    /* 6 */
    {
        "_id" : ObjectId("5672a8b7a5543ad892916a4f"),
        "name" : "S",
        "role" : "r3"
    }

    /* 7 */
    {
        "_id" : ObjectId("5672a8b7a5543ad892916a50"),
        "name" : "G",
        "role" : "r6"
    }

    /* 8 */
    {
        "_id" : ObjectId("5672a8b7a5543ad892916a51"),
        "name" : "H",
        "role" : "r2"
    }
预期产出:

-- input is role `r1` then (Need to show the name if `r1` is not associate already) -- same description for all the roles

    {"name" : "S"},
    {"name" : "G"},
    {"name" : "H"}

    -- input is role 'r2' then

    {"name" : "S"},
    {"name" : "G"}

    -- input is role 'r3' then

    {"name" : "B"},
    {"name" : "G"},
    {"name" : "H"}

    -- input is role 'r4' then

    {"name" : "B"},
    {"name" : "S"},
    {"name" : "G"},
    {"name" : "H"}

    -- input is role 'r6' then

    {"name" : "A"},
    {"name" : "B"},
    {"name" : "S"},
    {"name" : "H"}

非常感谢您的帮助。如何实现这一点。
aggregation
framework还是普通的find查询?请给出建议。

您可以尝试使用聚合:

db.getCollection('roles').aggregate([
    {$group: {_id:"$name", "roles":{$addToSet:"$role"}}},
    {$project: {_id:1, "roles": 1, "isSubset": { $setIsSubset: [ ["r1"], "$roles" ] }}},
    {$match: {"isSubset": false}},
    {$group: {_id:"$isSubset", "name": {$push : "$_id"}}},
    {$project: {"_id": 0, "name": 1}},
    {$unwind: "$name"}
])
  • 按名称分组,并将角色推送到数组中
  • 创建“IsubSet”字段,该字段指示您的“角色”是否是
    roles
    array”的子集
  • 仅搜索“isSubset”字段为false的对象
  • 按“发布集”分组
  • 仅显示“名称”字段
  • 展开“名称”

  • 我找到了一个比已经被接受的答案更好的方法来获得这个结果,我认为性能会更好。请查看:

     db.collection.aggregate([
    { 
                      $group: { _id: null,             
                          rightrole: { $addToSet:  { $cond : {if: { $ne: [ "$role", "r1" ] }, then: "$name", else: null }} }, 
                          wrongrole: { $addToSet:  { $cond : {if: { $eq: [ "$role", "r1" ] }, then: "$name", else: null } } } } 
                              }, 
              {   "$project": {"_id": 0,         
                             "name": { "$setDifference": [ "$rightrole", "$wrongrole" ] } }
    },              {$unwind: "$name"}
    ]);
    
  • 查找不在当前角色中的名称列表并将其添加 到一个数组
  • 查找当前角色中的名称列表 并将其添加到数组中
  • 找出两个数组之间的差异 使用$setDifference操作符
  • 展开名称

  • 请让我知道去那里的路done@Hecnanae:你太棒了。你让我开心了。工作得很好。非常感谢。如果我们使用此聚合,是否有任何性能命中率会上升?我不知道。它应该是在测试性能。我推荐这个。