加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ruby MongodB – 在处理多个集合时提高速度

发布时间:2020-12-17 02:49:42 所属栏目:百科 来源:网络整理
导读:我正在使用MongoDB和 Ruby使用mongo gem. 我有以下场景: 对于集合中的每个文档,请说出coll1,查看key1和key2 在另一个集合中搜索文档,将coll2与key1和key2的值匹配 如果匹配,则添加在#2中获取的文档,其中新的键key3的值设置为#1中引用的文档中key3的值 将更
我正在使用MongoDB和 Ruby使用mongo gem.

我有以下场景:

>对于集合中的每个文档,请说出coll1,查看key1和key2
>在另一个集合中搜索文档,将coll2与key1和key2的值匹配
>如果匹配,则添加在#2中获取的文档,其中新的键key3的值设置为#1中引用的文档中key3的值
>将更新的哈希插入到新的集合coll3中

MongoDB的一般准则是处理应用程序代码中的交叉收集操作.

所以我做了以下事情:

client = Mongo::Client.new([ '127.0.0.1:27017' ],:database => some_db,:server_selection_timeout => 5)
    cursor = client[:coll1].find({},{ :projection => {:_id => 0} }) # exclude _id
    cursor.each do |doc|
        doc_coll2 = client[:coll2].find('$and' => [{:key1 => doc[:key1]},{:key2 => doc[:key2] }]).limit(1).first # no find_one method
        if(doc_coll2 && doc[:key3])
            doc_coll2[:key3] = doc[:key3]
            doc_coll2.delete(:_id) # remove key :_id
            client[:coll3].insert_one(doc_coll2)
        end
    end

这可行,但是完成这项工作需要花费大量时间 – 收集coll1中的每个文档大约250ms或者大约15000条记录的3600s(1小时),这看起来很多,这可能与一次读取一个文档有关,检查应用程序代码,然后一次将一个文档写回新的集合.

有没有办法让这项操作更快完成?我正在做的方式甚至是正确的方法吗?

示例文档

> coll1

{
    "_id" : ObjectId("588610ead0ae360cb815e55f"),"key1" : "115384042","key2" : "276209","key3" : "10101122317876"
}

> coll2

{
    "_id" : ObjectId("788610ead0ae360def15e88e"),"key4" : 10,"key5" : 4,"key6" : 0,"key7" : "false","key8" : 0,"key9" : "false"
}

> coll3

{
    "_id" : ObjectId("788610ead0ae360def15e88e"),"key3" : "10101122317876","key9" : "false"
}

解决方法

解决方案是使用聚合,并在一个查询中执行此操作:

>使用$lookup在key1字段上执行连接
>使用$unwind解开数组
>使用$redact将doc1.key2 == coll2.key2保留在doc中
>使用$project重新格式化文档
>用$out将它写入coll3

所以查询将是:

db.coll1.aggregate([
    { "$lookup": { 
        "from": "coll2","localField": "key1","foreignField": "key1","as": "coll2_doc"
    }},{ "$unwind": "$coll2_doc" },{ "$redact": { 
        "$cond": [
            { "$eq": [ "$key2","$coll2_doc.key2" ] },"$$KEEP","$$PRUNE"
        ]
    }},{ 
      $project: {
         key1: 1,key2: 1,key3: 1,key4: "$coll2_doc.key4",key5: "$coll2_doc.key5",key6: "$coll2_doc.key6",key7: "$coll2_doc.key7",key8: "$coll2_doc.key8",key9: "$coll2_doc.key9",} 
    },{$out: "coll3"} 
],{allowDiskUse: true} );

和db.coll3.find()将返回

{
    "_id" : ObjectId("588610ead0ae360cb815e55f"),"key9" : "false"
}

编辑:MongoDB 3.4解决方案

如果您不想在$project阶段指定所有键,则可以利用$addFields和$replaceRoot,MongoDB 3.4中引入的两个新运算符

查询将变为:

db.coll1.aggregate([
    { "$lookup": { 
        "from": "coll2",{$addFields: {"coll2_doc.key3": "$key3" }},{$replaceRoot: {newRoot: "$coll2_doc"}},{allowDiskUse: true})

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读