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

Can I calculate the similarity of document fields using 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}]

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

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

免责声明:尽管它看起来像是大学作业,但实际上并非如此。这是一个个人项目。

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

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

其中size(T)为集合中的元素个数T&为集合交集,|为集合并集。要使用聚合框架进行计算,请使用以下(粗略)管道:

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

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