mongodb设计用于快速查询范围

时间:2014-11-14 11:44:01

标签: mongodb nosql

目前,我有一个mongoDb集合,其中包含以下类型的文档(~1000个文档):

{   _id : "...",
     id : "0000001",
   gaps : [{start:100, end:110}, {start:132, end:166}...], // up to ~1k elems
  bounds: [68, 88, 126, 228...],                           // up to 100 elems
  length: 300,
    seq : "ACCGACCCGAGGACCCCTGAGATG..."
}

"间隙"和#34;界限"数组中的值是指" seq"中的坐标。和"长度"是指" seq"长度。 我已经在" id"," gap"上定义了索引。和#34;界限"。 我需要根据坐标范围进行查询。例如,给出" from = 100"和"到= 200"我想为每个文档检索一个" gap"的子数组,一个" bounds"的子数组。和" seq"位于范围内的子串(在这种情况下介于100和200之间)。 现在,这是使用以下聚合管道完成的:

    db.annot.aggregate(
         {$match  : {"id" : "000001"}},
         {$unwind : "$gaps"},
         {$unwind : "$bounds"},
         {$match: {
                    $or :[
                         {"gaps.start" : {$gte:from, $lte:to}},
                         {"gaps.end" : {$gte:from, $lte:to}},
                         {"bounds" : {$gte:from, $lte:to}}
                    ]
                  }
         },
         {$project:{
                 id:1,
                 gaps:1,
                 bounds:1,
                 subseq:{$substr:["$seq", from, (to-from)]}}},
         {$group : {
                 _id : "$id",
                 gaps : {"$addToSet" : "$gaps"},
                 bounds : {"$addToSet" : "$bounds"},  
                 subseq : {"$first" : "$subseq"}}},
    )                                                                                                                         
  • 查询整个集合(省略第一个" $ match"在管道中)大约需要14秒。
  • 单独查询所有文件顺序每个文件最多需要50毫秒(总共约19秒)。
  • 单独查询所有文件并行总共需要约7秒。
  • 使用仅与id匹配的管道(即使用管道中的第一个" $ match")查询总共需要约5秒。

什么是最佳的数据库和查询设计,以最大限度地提高此类查询的性能?

1 个答案:

答案 0 :(得分:1)

  

最大化这种查询性能的最佳数据库和查询设计是什么?

由于您要求改进代码和设计,我建议您切换到最新版本的mongodb(如果您还没有)。这应该是一个很好的起点。对于这些类型的问题,基本的想法应该是reduce number of documents input每个pipeline operation

我建议你有一个名为range的额外变量,其中包含所有数字between fromto,包括两者。这允许我们在$intersection数组上应用bounds等函数。

所以变量,来自环境的聚合操作需求应该是:

var from = x; var to = y; var range=[x,...,y];
  • 第一步是匹配拥有的文档数量 我们范围内的idgaps子文档和bounds值。这个 减少输入到下一阶段的文件数量,即500。
  • 下一步是$redact 不符合的差距子 文档。此阶段现在适用于在过滤的500个文档 上一步。
  • 第三步是根据我们的需要$project我们的字段。

请注意,我们需要才能在任何地方使用$unwind运算符并完成任务。

db.collection.aggregate([
{$match  : {"id" : "0000001",
            "gaps.start":{$gte:from},
            "gaps.end":{$lte:to},
            "bounds" : {$gte:from, $lte:to}}},
{$redact:{
         $cond:[
                 {$and:[
                        {$gte:[{$ifNull: ["$start", from]},from]},
                        {$lte:[{$ifNull: ["$end", to]},to]}
                       ]},"$$DESCEND","$$PRUNE"
               ]
         }},
{$project: {
            "bounds":{$setIntersection:[range,"$bounds"]},
            "id":1,
            "gaps":1,
            "length":1,
            "subseq":{$substr:["$seq", from, (to-from)]}}}
])