Node.js 在MongoDB中,我使用了一个大型查询,即如何创建复合索引或单个索引,以提高响应时间

Node.js 在MongoDB中,我使用了一个大型查询,即如何创建复合索引或单个索引,以提高响应时间,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,在我的项目中,我有一个帖子集,这是一个方案: posts:{ title: {type: String, required: false}, text: {type: String, required: false}, plainDescription: {type: String, required: false}, isBlog: {type: Boolean,d

在我的项目中,我有一个帖子集,这是一个方案:

posts:{
        title:            {type: String, required: false},
        text:             {type: String, required: false},
        plainDescription: {type: String, required: false},
        isBlog:           {type: Boolean,default: false},
        type:             {type: String, required: true, default:'USER', enum:["USER","GROUP"]},
        information:{
            tags:[],
            users:[],
            groups:[],
            likes:[],
            likesCount:   {type: Number, default: 0},           
            dislikes:[],
            dislikesCount:{type: Number, default: 0},
            spams:[],
            spamsCount:   {type: Number, default: 0},
            shares:[],
            sharesCount:  {type: Number, default: 0},
            comments:[],
            commentsCount:{type: Number, default: 0},
            reply:[],
            favorite: [],
            favoriteCount:{type: Number, default: 0},
            replyCount:   {type: Number, default: 0}
        },
        authorId            : { type: String, required: true},// Can be user Id or Group Id
        authorName          : { type: String, required: false},
        isReply             : { type: Boolean, default: false},
        replyOf             : { type: String, default: "",nullable: true, references: 'posts._id'},
        isQuoteReyell       : { type: Boolean, default: false},
        quoteReyellOf       : { type: String, default: "",nullable: true, references: 'posts._id'},
        createdAt           : { type: Date, default: Date.now},
        createdBy           : { type: String, required: false, references: 'users._id'},
        creatorName         : { type: String, required: true, references: 'users.userName'},
        updatedAt           : { type: Date, required: false,default: Date.now},
        updatedBy           : { type: String, required: false, references: 'users._id'},
        updatorName         : { type: String, required: false, references: 'users.userName'},
        publishedAt         : { type: Date, required: false},
        isBlockedByAdmin    : {type:  Boolean,default: false},
        isDelete            : {type:  Boolean,default: false},
        isRss               : {type:  Boolean,default: false},
        updatedObj          : [],
        sportName           : {type: String, default: ''},
        teamObj             : []
    },
根据我的要求,以下是查询:

[{"$match":{"$and":[{"$or":[{"$and":[{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"createdAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isQuoteReyell":{"$ne":true}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":"reyell","updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"isReply":false}]},{"$and":[{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isReply":true},{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"updatedAt":{"$lt":"2017-10-26T06:17:32.533Z"}}]},{"$and":[{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":{"$ne":"reyell"},"updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"createdAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"isBlog":false},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isQuoteReyell":{"$ne":true}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":"reyell","updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"isReply":false}]},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"$and":[{"isReply":true},{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"updatedAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":{"$ne":"reyell"},"updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]}]},{"isBlockedByAdmin":false},{"isDelete":false}]}},{"$unwind":"$updatedObj"},{"$match":{"$or":[{"$and":[{"updatedObj.type":"reyell"},{"updatedObj.userId":{"$in":["5754c557bd961f3751ddd830"]}}]},{"$and":[{"updatedObj.type":"create"}]}]}},{"$group":{"_id":"$_id","updated":{"$last":"$updatedObj"},"post":{"$last":"$$ROOT"}}},{"$sort":{"updated.updatedAt":-1}},{"$limit":15}]

请帮助我,对于哪一列,我应该创建一个索引或复合索引,这样可以提高响应时间。

一般来说,您需要在最重要/最频繁查询中用作筛选条件的字段上放置索引,首先从最有选择性的字段开始。有一些相当不错的。对于您的案例,其中一个特别有趣的陈述可能是,因为您有很多
$或
s:

通常,MongoDB只使用一个索引来完成大多数查询。 但是,$or查询的每个子句可能使用不同的索引,并且 从2.6开始,MongoDB可以使用多个索引的交集

然而,这里最重要的事情是使用度量、度量、度量和查看查询执行计划。原因是,您的应用程序可能需要支持不同类型的查询,您需要在索引维护成本(例如,在索引更新和磁盘空间需求期间)之间进行权衡理论上最快的解决方案是,一个查询中使用的所有字段都由一个索引覆盖

整个索引主题有点模糊,很大程度上取决于您的具体场景:

  • 您的数据是否进行了大量更新,写操作是否需要超快速(您需要更少/更小的索引),或者您的数据是否非常稳定,并且必须快速频繁地读取(使用更多/更大的索引)
  • 您需要支持哪些类型的查询?它们的过滤器有多相似?某些过滤器的组合比其他过滤器的组合更有可能吗?哪些查询需要很好地执行,哪些查询可以稍微慢一点
  • 潜在索引字段中的数据是如何分布的
  • 等等
您将无法找到一个索引来帮助所有查询实现最佳性能。而且,当添加更多索引或更改现有索引时,这可能会导致查询优化器停止对某些查询使用某些索引,而选择不同的执行计划,这可能是需要的,也可能不是需要的。因此,在索引或物理数据布局(硬件设置、分片…)发生任何更改时,测量所有重要的内容。最后,您应该随着数据量的增长定期测量查询性能,除非数据的分布可以预测是一致的

长话短说:采用迭代方法,从添加索引开始(我建议在
isBlockedByAdmin
isDelete
information.shares.userId
)然后测量查询性能,然后根据您的发现优化索引(一次又一次,…)