获得两个不同结构的集合的区别

假设我有两个集合, AB

A包含以下forms的简单文档:

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

B包含这样的嵌套对象:

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

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

我们称他们为“孤儿”。

我现在的问题是:如何以最有效的方式find那些孤儿文件? 最后,我需要的是他们的_id领域。

到目前为止,我已经使用unwind来“扁平化” A ,并使用lambda的differenceWith函数来计算差异,但这需要相当长的时间,并且肯定不是很有效,因为我在客户端上完成所有工作,而不是在数据库。

我已经看到,在MongoDB中有一个$setDifference运算符,但我没有得到它的工作。

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

在MongoDb中,您可以使用您正在尝试的聚合pipe道。 如果这没有帮助你可以使用MapReduce,但它有点复杂。

在这个例子中,我命名了两个集合“Tags”和“Papers”,其中标签在您的示例中被命名为“B”,并且Papers将是“A”。

首先,我们得到一组实际存在的值,并引用文档。 为此,我们将标签集合中的每个值拼合起来,并将其打包在一起。 展开使用“values”数组中每个值的原始_id创build一个文档。 这个平面列表然后重新收集,他们的ID被忽略。

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

这返回:

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

该列表是所有文档中所有值的集合。

然后,创build一个类似的集合,包含可用文档的一组标签。 这不需要展开步骤,因为_id是标量值(=不是列表)

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

生产

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

正如您已经看到的那样,从我放入数据库的集合中,似乎在A中有一个ID为“D”的Document(Paper),它在tags集合中没有被引用,并且在orrhan之前。

你现在可以用你喜欢的任何方式来计算差异,这可能会很慢,但是适合作为一个例子:

 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") } 

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

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

标签在哪里

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

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