在我的项目中,我有一个帖子集合,这是方案:
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}]
请帮助我,对于哪一栏,我应该创建一个索引或复合索引,这样可以增加响应时间。
答案 0 :(得分:3)
通常,您需要在最重要/频繁查询中最常用作过滤条件的字段上放置索引,首先从最具选择性的字段开始。有一些不错的guidance on the topic as part of the MongoDB documentation。因为你有很多$or
s,所以对你的案例特别感兴趣的一个陈述可能就是这样:
通常,MongoDB只使用一个索引来完成大多数查询。 但是,$或查询的每个子句可以使用不同的索引,和 从2.6开始,MongoDB可以使用多个索引的交集。
然而,最重要的是使用explain()来衡量,衡量,衡量和查看查询执行计划。原因是您很可能会遇到应用程序需要支持的不同类型的查询,并且您需要在某些时候进行权衡,在这种情况下您必须在索引维护成本之间进行选择(例如write locks期间索引更新和磁盘空间要求)以及理论上最快的解决方案,其中单个查询中使用的所有字段都由单个索引覆盖。
整个索引主题有点模糊,严重依赖于您的精确场景:
您将找不到帮助您的所有查询执行最佳操作的单一索引。而且,当添加更多索引或更改现有索引时,这可能导致查询优化器停止对某些查询使用某些索引,并选择不同的执行计划,而这可能是也可能不需要。因此,在对索引或物理数据布局(硬件设置,分片......)进行任何更改时,请测量所有重要信息。最后,您应该随着数据量的增长定期衡量您的查询效果,除非它的分布在预测上是统一的。
简而言之:寻找迭代方法并首先添加索引(我建议在isBlockedByAdmin
,isDelete
和information.shares.userId
添加一个)然后衡量你的查询性能,然后根据您的发现(再次,再次,......)优化您的索引。