如何找到破碎的“外键”关系的等价物?

时间:2015-05-23 03:04:10

标签: mongodb mongodb-query

如果这是一个关系数据库,我有两个集合,我们称之为“一对一关系”。我不知道为什么一个没有嵌套在另一个中,但事实是对于集合“A”中的每个文档,都有一个集合“B”的文档,反之亦然。

当然,在没有外键约束的情况下,并且在存在错误的情况下,有时“A”中的文档中没有“B”中的相关文档(反之亦然)。

我是MongoDB的新手,我在创建查询或脚本时遇到问题,该查询或脚本会找到“A”中没有“B”中相关文档的所有文档(反之亦然)。我想我可以使用某种循环,但我还不知道它是如何工作的 - 我刚刚开始在RoboMongo命令行上使用简单的查询。

任何人都可以让我开始使用脚本吗?我见过“Verifying reference (foreign key) integrity in MongoDB”,但这对我没有帮助。一个错误导致“参照完整性”崩溃,我需要脚本以帮助我追踪错误。我也无法重新设计数据库以使用嵌入(虽然我希望我会问为什么一个文档没有嵌套在另一个文档中。)

我也看过“How to find items in a collections which are not in another collection with MongoDB”,但它没有答案。

不良技术的伪代码

var misMatches = [];
var collectionB = db.getCollection('B');
var allOfA = db.getCollection('A').find();
while (allOfA.hasNext()) {
    var nextA = allOfA.next();
    if (!collectionB.find(nextA._id)) {
        misMatches.push(nextA._id);
    }
}

1 个答案:

答案 0 :(得分:3)

我不知道这是否能很好地扩展,但是......

...给定此样本日期设置:

> db.a.insert([{a:1},{a:2},{a:10}       ])
> db.b.insert([      {b:2},{b:10},{b:20}])
//             ^^^^^              ^^^^^^
//                inconsistent 1-to-1 relationship

您可以使用map-reduce收集a中的密钥集,并将其与来自b的密钥集合合并:

mapA=function() {
  emit(this.a, {col: ["a"]})
}

mapB=function() {
  emit(this.b, {col: ["b"]})
}

reduce=function(key, values) {
  // merge both `col` arrays; sort the result
  return {col: values.reduce(
                 function(a,b) { return a.col.concat(b.col) }
                            ).sort()}
}

产:

> db.a.mapReduce(mapA, reduce, {out:{replace:"result"}})
> db.b.mapReduce(mapB, reduce, {out:{reduce:"result"}})
> db.result.find()
{ "_id" : 1, "value" : { "col" : [ "a" ] } }
{ "_id" : 2, "value" : { "col" : [ "a", "b" ] } }
{ "_id" : 10, "value" : { "col" : [ "a", "b" ] } }
{ "_id" : 20, "value" : { "col" : [ "b" ] } }

然后很容易找到在集合ab中找不到的所有ID。此外,您应该能够在一个或另一个集合中发现重复的密钥:

> db.result.find({"value.col": { $ne: [ "a", "b" ]}})
{ "_id" : 1, "value" : { "col" : [ "a" ] } }
{ "_id" : 20, "value" : { "col" : [ "b" ] }