【问题标题】:Deduplicaton / matching in Couchdb?Couchdb中的重复数据删除/匹配?
【发布时间】:2012-10-22 18:14:50
【问题描述】:

我在 couchdb 中有文档。架构如下所示:

userId
email
personal_blog_url
telephone

我假设两个用户实际上是同一个人,只要他们有

  • 电子邮件或
  • personal_blog_url 或
  • 电话

完全相同。

我创建了 3 个视图,基本上将 email/blog_url/telephone 映射到 userIds,然后将 userIds 组合到同一键下的组中,例如,

_view/by_email:
----------------------------------
key                   values     
a_email@gmail.com    [123, 345]
b_email@gmail.com    [23, 45, 333]

_view/by_blog_url:
----------------------------------
key                   values     
http://myblog.com    [23, 45]
http://mysite.com/ss [2, 123, 345]

_view/by_telephone:
----------------------------------
key                   values     
232-932-9088          [2, 123]
000-111-9999          [45, 1234]
999-999-0000          [1]

我的问题:

  • 如何将 3 个不同视图的结果合并到不包含重复项的最终用户表/视图中?
  • 或者在 couchdb 中进行这种重复数据删除是否是一种好习惯?
  • 或者在沙发上进行重复数据删除的好方法是什么?

ps。在最终视图中,假设对于所有受骗者,我们只保留最小的 userId。

谢谢。

【问题讨论】:

    标签: mapreduce couchdb matching deduplication


    【解决方案1】:

    好问题。也许您可以收听_changes 并在您建议的视图中搜索您希望对真实用户唯一的字段 (by_*)。

    • 将视图合并为一个(在一张地图中发出不同的字段):

      函数(文档){ 如果 (!doc.email || !doc.personal_blog_url || !doc.telephone) 返回; 发射([1,doc.email],[doc._id]); 发射([2,doc.personal_blog_url],[doc._id]); 发射([3,doc.telephone],[doc._id]); }

    • 在reduce中合并id的列表

    • 当更改提要中的新文档到达时,您可以使用keys=[[1, email], [2, personal_blog_url], ...] 查询视图并将三个列表合并。如果其最小 id 小于更改后的文档,则更新字段 realId,否则使用更改后的 id 更新列表中的文档。

    我建议使用不同的文档来存储{ userId, realId } 关系。

    【讨论】:

    • 谢谢马尔辛。我认为你的想法有效。直到最后一步我才获得成功——使用多个键进行搜索。如果我设置keys=[[1, "a@b.com"], [2, "http://a.com"], [3,"334-333-2323"]],我总是得到所有匹配的文档作为结果。也许我应该为此问一个关于 stackoverflow 的新问题?
    • 我不确定“所有文件”是什么意思。如果不使用reduce(仅映射),您应该获得带有"rows": [{"id": "1", "key": [1, "some@email"], "value": "1"}, {"id": "2", "key": [1, "some@email"], "value": "2"}, ... }] 的所有包含电子邮件、博客网址或电话号码的文档的响应JSON 记录。和你的新记录一样。你有没有得到一些没有这些字段匹配的文件?请注意,对于仅 map(不带 reduce)文档,不会按用户 ID 排序。
    • 我假设?keys=[[1, "a@b.com"], [2, "http://a.com"], [3,"334-333-2323"]] 是一个多键查询。我得到的结果包含一些没有这些字段匹配的文档。如果我只做单键查询,结果是正确的。多键查询有问题吗?顺便说一句,我使用的是 couchDB 1.0.1。
    • 是的,keys 应该与合并结果的多个 key 查询相同。我不知道为什么你的案例接缝不起作用:(我已经运行了这个地图和查询,但我不知道如何在 CouchDB 1.2.0 中对我的数据重现这种效果......唯一让我想到的是一个注释在文档中 (wiki.apache.org/couchdb/HTTP_view_API#Querying_Options) >我没有使用reduce,只是map。
    【解决方案2】:

    您不能仅使用视图来创建新文档。您需要某种任务来进行实际的合并。

    这是一个想法。

    您可以创建一个视图(如果数据存在则索引数据),而不是创建 3 个视图:

    Key                             Values
    ---                             ------
    [userId, 'phone']               777-555-1212
    [userId, 'email']               username@example.com
    [userId, 'url']                 favorite.url.example.com
    

    除了原始值之外,我不会存储任何其他内容,因为您最终会得到大量不必要的数据重复(例如,如果您存储了完整的对象)。

    然后,要查询,您可以执行以下操作:

    ...startkey=[userId]&endkey=[userId,{}]
    

    这会将所有重复信息作为该用户 ID 的一系列文档提供给您。您仍然需要对其进行解析以查看是否存在重复项。但是,通过这种方式,结果将很好地合并到单个 CouchDB 调用中。

    Here's 在 StackOverflow 上使用数组作为键的一个很好的例子。

    如果原始“用户”文档包含不属于重复数据删除过程的其他数据,您仍然可能会加载它。

    一旦发现,您可以考虑即时清理数据,并防止在将新数据输入您的应用程序时出现新的重复数据。

    【讨论】:

    • 谢谢。这种方法似乎适用于每个用户都有重复信息的情况。但我需要的是对用户进行重复数据删除(使用不同的用户 ID,但有共同的电子邮件/网址/电话)。
    猜你喜欢
    • 2019-02-12
    • 1970-01-01
    • 2018-08-03
    • 2014-10-19
    • 2022-01-18
    • 1970-01-01
    • 2014-02-23
    • 2019-02-13
    • 1970-01-01
    相关资源
    最近更新 更多