我正在使用 mongoose 来计算与特定查询匹配的文档数量。我对该查询的索引是:{createdAt: -1, status: -1, oId: -1}
Mongo版本为3.2,馆藏文档量约175万。
如果我这样做:
model.find({
createdAt: {'$gte': threeMonths, '$lt': today},
status: {'$in': model.STATUS_SET}
}).select({_id: 0, status: 1}).count().then((c) => result[alias] = c)
这需要超过 2 分钟。但如果我这样做:
model.find({
createdAt: {'$gte': threeMonths, '$lt': today},
status: {'$in': model.STATUS_SET}
}).select({_id: 0, status: 1}).lean().then((c) => result[alias] = c.length)
然后大约需要 2.5 秒。
我做错了什么?我可以做些什么来加快速度?
编辑:解释日志。
计数:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 0,
"executionTimeMillis" : 82671,
"totalKeysExamined" : 1749689,
"totalDocsExamined" : 1643722,
"executionStages" : {
"stage" : "COUNT",
"nReturned" : 0,
"executionTimeMillisEstimate" : 80960,
"works" : 1750066,
"advanced" : 0,
"needTime" : 1749689,
"needFetch" : 376,
"saveState" : 14662,
"restoreState" : 14662,
"isEOF" : 1,
"invalidates" : 0,
"nCounted" : 1643722,
"nSkipped" : 0,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 80890,
"works" : 1750065,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 376,
"saveState" : 14662,
"restoreState" : 14662,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 1643722,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 3800,
"works" : 1749689,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 0,
"saveState" : 14662,
"restoreState" : 14662,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"createdAt" : -1,
"status" : -1,
"oId" : -1
},
"indexName" : "moderatedContent",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"createdAt" : [
"(new Date(1467195213000), new Date(1459246413000)]"
],
"status" : [
"[\"UNDECIDED\", \"UNDECIDED\"]",
"[\"APPROVED\", \"APPROVED\"]"
],
"oId" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 1749689,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0
}
}
},
"allPlansExecution" : [ ]
}
用于查找。
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1643722,
"executionTimeMillis" : 1216,
"totalKeysExamined" : 1749689,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 1080,
"works" : 1749690,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 0,
"saveState" : 13669,
"restoreState" : 13669,
"isEOF" : 1,
"invalidates" : 0,
"transformBy" : {
"_id" : 0,
"status" : 1
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 920,
"works" : 1749690,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 0,
"saveState" : 13669,
"restoreState" : 13669,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"createdAt" : -1,
"status" : -1,
"oId" : -1
},
"indexName" : "moderatedContent",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"createdAt" : [
"(new Date(1467195213000), new Date(1459246413000)]"
],
"status" : [
"[\"UNDECIDED\", \"UNDECIDED\"]",
"[\"APPROVED\", \"APPROVED\"]"
],
"oId" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 1749689,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0
}
}
}
对于游标中第一个带有 .explain() 的帖子:
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 0,
"executionTimeMillis" : 89191,
"totalKeysExamined" : 1749689,
"totalDocsExamined" : 1643722,
"executionStages" : {
"stage" : "COUNT",
"nReturned" : 0,
"executionTimeMillisEstimate" : 83400,
"works" : 1751709,
"advanced" : 0,
"needTime" : 1749689,
"needFetch" : 2019,
"saveState" : 15648,
"restoreState" : 15648,
"isEOF" : 1,
"invalidates" : 0,
"nCounted" : 1643722,
"nSkipped" : 0,
"inputStage" : {
"stage" : "FETCH",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 83260,
"works" : 1751708,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 2019,
"saveState" : 15648,
"restoreState" : 15648,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 1643722,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1643722,
"executionTimeMillisEstimate" : 8290,
"works" : 1749689,
"advanced" : 1643722,
"needTime" : 105967,
"needFetch" : 0,
"saveState" : 15648,
"restoreState" : 15648,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"createdAt" : -1,
"status" : -1,
"oId" : -1
},
"indexName" : "moderatedContent",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"createdAt" : [
"(new Date(1467195213000), new Date(1459246413000)]"
],
"status" : [
"[\"UNDECIDED\", \"UNDECIDED\"]",
"[\"APPROVED\", \"APPROVED\"]"
],
"oId" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 1749689,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0
}
}
}
}
最佳答案
你的答案的关键是
//count
"totalDocsExamined" : 1643722,
对比
//find
"totalDocsExamined" : 0,
查找查询完全在索引上运行,不读取任何单个文档,而计数查询实际上从数据库中读取每个文档。
原因是,您的查找查询使用了 lean() 选项。据 Mongoose doc :
Documents returned from queries with the lean option enabled are plain javascript objects, not MongooseDocuments. They have no save method, getters/setters or other Mongoose magic applied.
最重要的是,在您的精益查找查询中,您只是 select()ing id 和 status,这似乎是预计的("transformBy"...) 这样整个查询就变成了一个 covered query 并且无需阅读任何文档即可满足请求。
关于javascript - mongodb -- count() 比 find() 慢多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38097190/
当谈到运行时自省(introspection)和动态代码生成时,我认为ruby没有任何竞争对手,可能除了一些lisp方言。前几天,我正在做一些代码练习来探索ruby的动态功能,我开始想知道如何向现有对象添加方法。以下是我能想到的3种方法:obj=Object.new#addamethoddirectlydefobj.new_method...end#addamethodindirectlywiththesingletonclassclass这只是冰山一角,因为我还没有探索instance_eval、module_eval和define_method的各种组合。是否有在线/离线资
有几种方法:first_or_create_by、find_or_create_by等,它们的工作原理是:与数据库对话以尝试找到我们想要的东西如果我们找不到,就自己做保存到数据库显然,并发调用这些方法可能会使两个线程都找不到它们想要的东西,并且在第3步中一个线程会意外失败。似乎更好的解决方案是,创建或查找即:提前在您的数据库中创建合理的唯一性约束。如果你想保存一些东西,就保存它如果有效,那就太好了。如果它因为RecordNotUnique异常而无法工作,它已经存在,太好了,加载它那么在什么情况下我想使用Rails内置的东西而不是我自己的(看起来更可靠)create_or_find?
给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我有一些模型需要在它们上面放置自定义查找条件。例如,如果我有一个联系人模型,每次调用Contact.find时,我都想限制返回的联系人只属于正在使用的帐户。我通过Google找到了这个(我对其进行了一些自定义):defself.find(*args)with_scope(:find=>{:conditions=>"account_id=#{$account.id}"})dosuper(*args)endend这很好用,除了少数情况下account_id不明确,所以我将其调整为:defself.find(*args)with_scope(:find=>{:conditions=>"#{s
我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
我有一个哈希条目数组,并希望根据传递给函数的参数进行过滤。如果散列中有三个值,A、B和C,我想做类似的事情:data=[{A:'a1',B:'b1',C:'c1'},{A:'a1',B:'b2',C:'c1'},{A:'a1',B:'b2',C:'c2'},{A:'a2',B:'b1',C:'c1'},{A:'a2',B:'b2',C:'c1'}]data.find_all{|d|d[:A].include?params[:A]}.find_all{|d|d[:B].include?params[:B]}.find_all{|d|d[:C].include?params[:C]}找到所
我正在使用来自learn-rails.com的“学习RubyOnRails”pdf书。我在第13章“配置”。我们应该在哪里执行命令:“railsgeneratefigaro:install”在第12章中,我们安装了figarogem:“我们已经在Gemfile中安装了figarogem并运行bundleinstall。”当我运行该命令时,我得到:“找不到生成器figaro:install。”我开始搜索类似的问题,我确实在这里找到了这个问题:railsgenerate-"Couldnotfindgenerator"他们被建议在命令中也包含“迁移”。我将它包含在我的命令中并让它做某事,但我
我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文