我可以使用MapReduce计算文档字段的相似度吗?

时间:2015-01-06 19:18:12

标签: mongodb mapreduce

据我所知,使用map reduce计算两个文档的Jaccard相似度是不可能的,因为map只需要一个项目。

我想计算文档字段元素的相似性。这可能使用map reduce吗?我目前无法看到发出什么。

输入:

{'_id': 'foobar1',
 'categories': ['one', 'two', 'three']}
{'_id': 'foobar2',
 'categories': ['one']}
{'_id': 'foobar3',
 'categories': ['one', 'two']}

我现在想要计算类别onetwothree彼此之间的相似程度,考虑它们所属的文档。这也可以说是在下面的集合中找到文档之间的相似性(仅在理想世界中,我不必将数据重新计算到此集合)。

{'_id': 'one'
 'documents': ['foobar1', 'foobar2', 'foobar3']}
{'_id': 'two',
 'categories': ['foobar1', 'foobar3']}
{'_id': 'three',
 'categories': ['foobar1']}

期望的输出:

{('one', 'two'): 2/3,
 ('one', 'three'): 1/3,
 ('two', 'three'): 1/2}

这是否可以使用map reduce以及如何使用?

到目前为止,我从地图中发出的内容如下:

[{('one', 'two'): 1},
 {('one', 'three'): 1},
 {('two', 'three'): 1},
 {('one', 'two'): 1}]

但当然在减少中我只能计算总和,因为我不知道S('one')S('three')的联合是什么。

我是否必须在map-reduce之后重新计算总和,或者我可以改变我的方法以便能够在0和1之间建立相似性(就像Jaccard那样)?

免责声明:即使它看起来像大学任务,但事实并非如此。这是个人项目。

1 个答案:

答案 0 :(得分:3)

我相信你可以使用聚合框架计算两个数组字段XY的Jaccard系数 - 你应该总是喜欢使用map / reduce。两组XY的Jaccard系数定义为

J(X, Y) = size(X & Y) / size(X | Y)

其中size(T)是集合T中的元素数量,&设置为交集,|设置为union。要使用聚合框架计算此值,请使用以下(粗略)管道:

db.test.aggregate([
    { "$project" : { "intersection" : { "$setIntersection" : ["$X", "$Y"] }, "union" : { "$setUnion" : ["$X", "$Y"] } } },
    { "$project" : { "jaccard" : { "$divide" : [{ "$size" : "$intersection" }, {"$size" : "$union" }] } } }
])

我将计算分为两个步骤以使其更清晰,但它可能是一个$project阶段。您可能需要添加额外的逻辑来处理XY都为空或其中一个不是数组或缺失的情况。预先设置$match阶段来计算文档子集的系数。