Mongodb $ redact通过比较子文档中的两个字段

时间:2014-05-14 18:52:41

标签: mongodb

我已更新到Mongodb 2.6.1并尝试使用新的$redact聚合功能来解决业务问题,但未成功。我遇到的所有$ redact示例都针对外部变量或静态值进行评估。

我需要根据兄弟子文档中的值消除一些生成的文档。如果可能的话,我相信$ redact将是这样做的方式,但是就像所有技术挑战一样,我确信有几种方法可以解决。我想保持文档结构不变。如果需要,我可以在我的应用程序代码中消除额外的结果,但更喜欢数据库中的数据恰到好处。

这就是我要做的......

该集合

Location.id是应用程序代码中的int集,仅用于创建位置和奖励之间的关系(奖励可能仅在几个位置有效)。以下文档已经减少,重点关注这里的重要内容。

{
    "_id" : ObjectId("53728b24e4749ce8ac3f31e7"),
    "name" : "Business name",
    "locations" : [ 
        {
            "name" : "Downtown Norfolk",
            "id" : 3
        }, 
        {
            "name" : "McDonald's Suffolk",
            "id" : 4
        }
    ],
    "rewards" : [ 
        {
            "name" : "Reward for Downtown Norfolk Only",
            "locationIDs" : [3]
        }
    ]
}

查询

我需要制作的是每个奖励及其适用位置的清单。我可以使用以下内容获取位置/奖励的完整列表...

collection.aggregate([
  { $unwind: '$rewards' },
  { $unwind:  '$locations' },                      
  { $project: { name: 1, rewards: 1, locations: 1 } }
  }    
])

查询结果

以下基本上将所有地点加入所有奖励。但是这个奖励只适用于location.id = 3,而不是3和4,所以我需要从结果中消除location.id = 4。我需要继续使用聚合,因为实际查询(此处未显示)包括$ geoNear。

{
    "result" : [ 
        {
            "_id" : ObjectId("53728b24e4749ce8ac3f31e7"),
            "name" : "Business name",
            "locations" : {
                "name" : "Downtown Norfolk",
                "id" : 3
            },
            "rewards" : {
                "name" : "Newport News Only Reward",
                "locationIDs" : [3]
            }
        }, 
        {
            "_id" : ObjectId("53728b24e4749ce8ac3f31e7"),
            "name" : "Business name",
            "locations" : {
                "name" : "McDonald's Suffolk",
                "id" : 4
            },
            "rewards" : {
                "locationIDs" : [3]
            }
        }
    ],
    "ok" : 1
}

我想要的查询结果

我要做的是从上面的查询结果中删除最后一个文档,其中locationID不匹配(其中locations.id = 4不在rewards.locationIDs = [3]中)。以下是我想从Mongo回来的内容。

{
    "result" : [ 
        {
            "_id" : ObjectId("53728b24e4749ce8ac3f31e7"),
            "name" : "Business name",
            "locations" : {
                "name" : "Downtown Norfolk",
                "id" : 3
            },
            "rewards" : {
                "name" : "Newport News Only Reward",
                "locationIDs" : [ 
                    3
                ]
            }
        }
    ],
    "ok" : 1
}

非常感谢。

1 个答案:

答案 0 :(得分:1)

不确定$ redact会有所帮助。我建议使用$ cmp运算符来比较值,如下所示:

db.ttt.aggregate({$unwind:"$locations"},
                 {$unwind:"$rewards"},
                 {$unwind:"$rewards.locationIDs"},
                 {$project:
                          {_id:1,
                           name:1,
                           locations:1,
                           rewards:1,
                           equality:{
                                     $cmp:['$locations.id','$rewards.locationIDs']
                                    }
                          }
                 },
                 {$match:{equality:0}})

它将排除不匹配的文档,然后您需要分组