V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
JCZ2MkKb5S8ZX9pq
V2EX  ›  MongoDB

mongodb 给数组插入不重复的内容

  •  
  •   JCZ2MkKb5S8ZX9pq · 2019-01-06 01:22:07 +08:00 · 5690 次点击
    这是一个创建于 2181 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求

    mongodb 里有一个字段,比如tags,有多个来源,来源都是数组,需要插入并去重。
    直观的方法是查询后去重,然后更新回去。
    网上看到还有 addToSet 这个命令。
    用两种方法都做了测试。

    先建一个临时表

    s = [i for i in range(10000)]
    for i in range(10000):
        db['test'].insert_one({'test_set': s})
    

    方法 1

    查询 /用旧列表和新列表合并 /更新

    s = [i for i in range(0, 20000, 2)]
    for i in db['test'].find():
        i['test_set'] = sorted(set(i['test_set']) | set(s))
        db['test'].update_one({'_id': i['_id']}, 
                              {'$set': {'test_set': i['test_set']}})
    

    方法 2

    网上看到的,用 addToSet。

    s = [i for i in range(0, 20000, 2)]
    for i in db['test'].find():
        i['test_set'] = sorted(set(i['test_set']) | set(s))
        db['test'].update_one({'_id': i['_id']},
                              {'$addToSet': {'test_set': {'$each': s}}})
    

    结论

    方法 2 超级超级慢,可能是 each 之后做了太多次查重导致的。
    本来还以为都在数据库端处理可能会快点,失败。
    跟大家分享下实验结果。

    附:$addToSet — MongoDB Manual

    如果有其它好的方法欢迎讨论。

    3 条回复    2020-04-07 11:05:11 +08:00
    swulling
        1
    swulling  
       2019-01-06 01:58:54 +08:00 via iPhone
    方法一有并发冲突问题,谨慎使用。
    myKing
        2
    myKing  
       2020-02-04 16:31:52 +08:00
    还有其他方法?
    sego
        3
    sego  
       2020-04-07 11:05:11 +08:00
    看了[官网的文档]( https://docs.mongodb.com/manual/reference/operator/update/addToSet/),想不重复地添加元素到数组里,好像只能 addToSet 。
    要不看下 CPU 占用高不高,不高的话多线程试试?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4742 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 09:51 · PVG 17:51 · LAX 01:51 · JFK 04:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.