Mongo:$exists 字段的索引
Posted
技术标签:
【中文标题】Mongo:$exists 字段的索引【英文标题】:Mongo: Index on $exists of field 【发布时间】:2014-08-01 10:59:36 【问题描述】:我有以下猫鼬模式:
var dataSchema = new Schema(
owner: type: Schema.ObjectId, ref: 'User' ,
time : type: Date, default: Date.now ,
eventCount:Number
);
对于某些 dataObjects,eventCount 已定义且为正数,对于其他 dataObjects,eventCount 未定义。我想设计一个索引,使这样的查询尽可能快:
db.datacollection.find(owner: <some ID>, eventCount: $exists:true, time: <some time range>)
最好的方法是什么?
这是我能想到的最佳解决方案,但我很想知道是否有人有更好的解决方案:
向 dataSchema 添加一个 isEventCount 布尔变量。设置 mongoose 中间件,以便在使用以下逻辑将对象保存到 db 之前计算 isEventCount。
if(eventCount > 0)
isEventCount = true;
else
isEventCount = false;
然后建立这样的索引
db.datacollection.ensureIndex(user:1, isEventCount: 1, time:1)
并像这样运行我的查询
db.datacollection.find(owner: <some ID>, isEventCount: true, time: <some time range>)
这种方法有几个缺点。即:
-
我正在数据库中保存冗余信息。
我必须编写额外的中间件代码来实现这一点。
我必须修改数据库中的现有条目。
有人知道更好的解决方案或可以帮助解决此问题的库吗?
【问题讨论】:
【参考方案1】:您不需要通过所有这些来获得该查询的良好性能。使用您现有的查询:
db.datacollection.find(owner: <some ID>, eventCount: $exists:true, time: <some time range>
这个索引:
db.datacollection.ensureIndex(user:1, eventCount: 1, time:1)
在大多数情况下应该会给你相当好的性能。显然我不知道您现有数据集的大小或分布,但我认为创建isEventCount
标志需要一些相当不寻常的东西。
一般来说,在对 MongoDB 中的架构设计采取任何不寻常的措施之前,我会执行以下操作:
1) 设置合理数量的测试数据 2) 使用 explain() 尝试查询
它会让您很好地了解查询的执行情况以及它如何/何时使用索引。
http://docs.mongodb.org/manual/reference/method/cursor.explain/#cursor.explain
【讨论】:
我试过这个。这行不通。假设我有以下数据: owner: UserA, dataCount: 1, time:昨天 owner: UserA, dataCount: 1, time: lastYear - 假设有 1000000 条这样的记录 owner: UserA, dataCount: 2,时间:昨天 你上面描述的索引会按照我上面描述的方式对记录进行排序。然后,如果我要运行查询: find(owner: UserA, eventCount:$exists: true, time: since昨天) 光标将不得不扫描去年的所有记录。 "doesn't work" 表示查询失败?还是你不喜欢表演?您可以从索引中删除时间字段 - 正如我所说,我不知道您的数据的大小和分布,只有您知道。关键是您不需要计算字段“isEventCount”。在任何情况下,您都应该对各种方法进行基准测试,看看哪些方法适合您——没有一种模式/索引方法适用于所有人和所有用例。 不起作用,因为我不喜欢这种表现。我想以某种方式设计我的索引,对于这个特定的查询,我希望nscanned
等于找到的对象的数量。使用我建议的方案是可能的,而使用您的方案是不可能的。 (以下玩具数据集就是这种情况: "datacount" : 1, "time" : ISODate("2013-06-10T15:29:32.603Z"), "exists" : true "datacount" : 2, "time" : ISODate("2014-06-10T15:29:32.603Z"), "exists" : true "datacount" : 1, "time" : ISODate("2014-06-10T15:29:32.603Z"), "exists" : true
)以上是关于Mongo:$exists 字段的索引的主要内容,如果未能解决你的问题,请参考以下文章