像MongoDb这样的查询具有排序性能

时间:2019-02-18 15:07:50

标签: regex mongodb performance sorting aggregation-framework

我正在使用mongodb 3.6,其中有Usermst集合,其中包含用户文档。我将获取更多帖子的用户名和姓氏。以下是我的mongodb查询。

    db.getCollection("UserMst").aggregate([
    {$match :{$and:[{os : {$in:[0,1]}}, {_id : {$nin : [3,10]}}]}}
    ,{$match:{$and:
         [ {$or: [
           {$and : [{fname:{$regex : `^has.*` , $options: 'i' }},{lname:{$regex : `^pa.*` , $options: 'i' }}]}  
          ,{$and:  [{fname:{$regex : `^pa.*` , $options: 'i' }}, {lname:{$regex : `^has.*` , $options: 'i' }}]}
          ]}
         ]
         }
    }
    ,{$sort:{'posts':-1,'_id':-1}}
    ,{$project:{"fname":1,"lname":1,"posts":1}}
    ,{$limit:5}
    ])

我的索引为“名称”:“ os_1_posts_-1”。该查询很耗时。有什么方法可以优化查询?

1 个答案:

答案 0 :(得分:0)

  1. 如果您查看匹配项:{$match :{$and:[{os : {$in:[0,1]}}, {_id : {$nin : [3,10]}}]}},可以看到您正在尝试在os_id上进行匹配-如果您尝试在_id上进行匹配,您通常会希望在索引中使用_id
  2. 在下一个$ match中,您尝试在fnamelname上进行匹配-如果未建立索引,这将很慢(并且OR通常很难建立索引)。看来这可能是基数最高的查询的一部分。
  3. 您实际上并未在此管道中使用任何聚合特定的功能!您可以将其编写为常规查询,并使用投影和限制。您还在不需要的地方使用$and

您的聚合管道的查询类似于:

{
  os: {$in: [0, 1] },
  _id : {$nin : [3,10]},
  $or: [
    {
      fname: { $regex: `^has.*` , $options: 'i' },
      lname:{ $regex: `^pa.*` , $options: 'i' }
    },
    {
      fname: {$regex : `^pa.*` , $options: 'i' },
      lname:{$regex : `^has.*` , $options: 'i' 
    }
  ]
}

然后依次在posts_id上排序

我不确定哪个字段的基数最大,您的数据是什么样的以及在此数据库上正在运行的其他查询是什么,因此很难推荐实际的索引,但是很难找到一个复合索引像{lname, fname, os, posts, _id}应该表现更好。