node.js – 获得两个不同结构的集合的区别

假设我有两个集合,A和B.

A包含以下形式的简单文档:

{ _id: '...',value: 'A',data: '...' }
{ _id: '...',value: 'B',value: 'C',data: '...' }
…

B包含这样的嵌套对象:

{ _id: '...',values: [ 'A','B' ]}
{ _id: '...',values: [ 'C' ]}
…

现在可能发生的是,A中的文档没有被B中的任何文档引用,或者B中的引用文档在A中不存在.

我们称他们为“孤儿”.

我现在的问题是:如何以最有效的方式找到这些孤立的文档?最后,我需要的是他们的_id字段.

到目前为止,我已经使用展开来“展平”A,并使用differenceWith function of Ramda计算差异,但这需要相当长的时间,并且肯定不是真正有效,因为我在客户端而不是在数据库中完成所有工作.

我已经看到MongoDB中有一个$setDifference运算符,但我没有让它工作.

任何人都可以指出我正确的方向,如何使用Node.js解决这个问题,并在数据库中运行大部分(全部?)工作?任何提示都表示赞赏:-)

解决方法

在MongoDb中,您可以使用聚合管道来处理您正在尝试的内容.如果这没有用,你可以使用MapReduce,但它有点复杂.

在这个例子中,我将两个集合命名为“Tags”和“Papers”,其中Tags在您的示例中命名为“B”,Papers将为“A”.

首先,我们获得实际存在的值集并引用文档.为此,我们将标签集合中的每个值展平并将其打包在一起.展开为’values’数组中的每个值创建一个带有原始_id的文档.然后重新收集此平面列表并忽略它们的ID.

var referenced_tags = db.tags.aggregate(
     {$unwind: '$values'},{$group: {
         _id: '',tags: { $push: '$values'}
     }
 });

返回:

{ "_id" : "","tags" : [ "A","B","C"] }

此列表是所有文档中所有值的集合.

然后,您创建一个类似的集合,其中包含可用文档的标记集.这不需要展开步骤,因为_id是标量值(=不是列表)

var papers = db.papers.aggregate(
    {$group: { 
        _id: '',tags: {$push: '$value'}
    }
});

生产

{ "_id" : "","C","D"] }

正如您已经看到的那样,从我放入数据库的集合中,A中似乎有一个文档(Paper),其ID为“D”,未在tags集合中引用,因此是一个孤儿.

您现在可以以任何您喜欢的方式计算差异集,这可能很慢,但适合作为示例:

var a = referenced_tags.tags;
var b = tags.tags;
var delta = a.filter(function (v) { return b.indexOf(v) < 0; });

下一步,您可以通过在delta中查找这些值并仅投影其ID来查找ID:

db.papers.find({'value' : {'$in': delta}},{'_id': 1})

返回:

{ "_id" : ObjectId("558bd2...44f6a") }

编辑:
虽然这很好地展示了如何使用聚合框架来解决这个问题,但这不是一个可行的解决方案.一个甚至不需要聚合,因为MongoDb非常聪明:

db.papers.find({'value' : {'$nin': tags.values }},{'_id': 1})

标签在哪里

var cursor = db.tags.find();
var tags = cursor.hasNext() : cusor.next() : null;

正如@ karthick.k所指出的那样

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...