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

Joh*_*ers 6 mongodb mongodb-query

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

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

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

任何人都可以让我开始使用脚本吗?我看过“验证 MongoDB 中的引用(外键)完整性”,但这对我没有帮助。一个错误导致“引用完整性”崩溃,我需要脚本来帮助我追踪该错误。我也无法重新设计数据库以使用嵌入(尽管我希望我会问为什么一个文档不嵌套在另一个文档中)。

我也看过“如何使用 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Syl*_*oux 3

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

...给定此示例日期集:

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

您可以使用 map-reduce 收集 in 中的键集a并将其与 from 中的键集合并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()}
}
Run Code Online (Sandbox Code Playgroud)

生产:

> 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" ] } }
Run Code Online (Sandbox Code Playgroud)

a然后很容易找到在 collection和中找不到的所有 id b。此外,您应该能够在一个或另一个集合中发现重复的键:

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