我使用Mongoid与mongo交互。如何在一个查询中组合两个索引? created_at上的一个索引和loc.coordinates上的另一个索引可以快速搜索我的数据?理想情况下,我不想进行全表扫描,我注意到我的2d索引,nscannedObjects命中每条记录(69)。
第三个查询应该有效,但失败是因为" planner返回错误:错误提示"
查询1:
@snaps = Snap.where(:created_at=>(2.days.ago..Time.now), :loc => { "$within" => { "$polygon" => hood }}).criteria.extras(:hint => {"created_at"=>-1}).order_by(:created_at => 'desc').limit(50).skip(offset).explain()
Query explain():
=> {"cursor"=>"BtreeCursor created_at_-1", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>15, "nscanned"=>15, "nscannedObjectsAllPlans"=>15, "nscannedAllPlans"=>15, "scanAndOrder"=>false, "indexOnly"=>false, "nYields"=>0, "nChunkSkips"=>0, "millis"=>0,
"indexBounds"=>{"created_at"=>[[2015-02-19 17:03:38 UTC, 2015-02-17 17:03:38 UTC]]},
"allPlans"=>[{"cursor"=>"BtreeCursor created_at_-1", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>15, "nscanned"=>15, "scanAndOrder"=>false, "indexOnly"=>false, "nChunkSkips"=>0,
"indexBounds"=>{"created_at"=>[[2015-02-19 17:03:38 UTC, 2015-02-17 17:03:38 UTC]]}}], "server"=>"snapdate:27017", "filterSet"=>false, "stats"=>{"type"=>"LIMIT", "works"=>17, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>12, "needFetch"=>0, "isEOF"=>1,
"children"=>[{"type"=>"FETCH", "works"=>17, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>12, "needFetch"=>0, "isEOF"=>1, "alreadyHasObj"=>0, "forcedFetches"=>0, "matchTested"=>4, "children"=>[{"type"=>"IXSCAN", "works"=>16, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>15, "needTime"=>1, "needFetch"=>0, "isEOF"=>1,
"keyPattern"=>"{ created_at: -1.0 }",
"isMultiKey"=>0, "boundsVerbose"=>"field #0['created_at']: [new Date(1424365418271),
new Date(1424192618271)]",
"yieldMovedCursor"=>0, "dupsTested"=>0, "dupsDropped"=>0, "seenInvalidated"=>0, "matchTested"=>0, "keysExamined"=>15, "children"=>[]}]}]}}
查询2:
@snaps = Snap.where(:created_at=>(2.days.ago..Time.now), :loc => { "$within" => { "$polygon" => hood }}).criteria.extras(:hint => {"loc.coordinates"=>'2d'}).order_by(:created_at => 'desc').limit(50).skip(offset).explain()
查询2解释():
=> {"cursor"=>"BtreeCursor loc.coordinates_2d", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>69, "nscanned"=>69, "nscannedObjectsAllPlans"=>69, "nscannedAllPlans"=>69, "scanAndOrder"=>true, "indexOnly"=>false, "nYields"=>0, "nChunkSkips"=>0, "millis"=>0, "indexBounds"=>{"loc.coordinates"=>[[{"$minElement"=>1}, {"$maxElement"=>1}]]}, "allPlans"=>[{"cursor"=>"BtreeCursor loc.coordinates_2d", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>69, "nscanned"=>69, "scanAndOrder"=>true, "indexOnly"=>false, "nChunkSkips"=>0, "indexBounds"=>{"loc.coordinates"=>[[{"$minElement"=>1}, {"$maxElement"=>1}]]}}], "server"=>"snapdate:27017", "filterSet"=>false, "stats"=>{"type"=>"SORT", "works"=>77, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>71, "needFetch"=>0, "isEOF"=>1, "forcedFetches"=>0, "memUsage"=>2671, "memLimit"=>33554432, "children"=>[{"type"=>"KEEP_MUTATIONS", "works"=>71, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>66, "needFetch"=>0, "isEOF"=>1, "children"=>[{"type"=>"FETCH", "works"=>71, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>66, "needFetch"=>0, "isEOF"=>1, "alreadyHasObj"=>0, "forcedFetches"=>0, "matchTested"=>4, "children"=>[{"type"=>"IXSCAN", "works"=>70, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>69, "needTime"=>1, "needFetch"=>0, "isEOF"=>1, "keyPattern"=>"{ loc.coordinates: \"2d\" }", "isMultiKey"=>0, "boundsVerbose"=>"field #0['loc.coordinates']: [MinKey, MaxKey]", "yieldMovedCursor"=>0, "dupsTested"=>0, "dupsDropped"=>0, "seenInvalidated"=>0, "matchTested"=>0, "keysExamined"=>69, "children"=>[]}]}]}]}}
第三次查询失败:
@snaps = Snap.where(:created_at=>(2.days.ago..Time.now), :loc => { "$within" => { "$polygon" => hood }}).criteria.extras(:hint => {"created_at"=>-1,"loc.coordinates"=>'2d'}).order_by(:created_at => 'desc').limit(50).skip(offset).explain()
第三次查询失败解释()
@selector={"$query"=>{"created_at"=>{"$gte"=>2015-02-17 17:10:39 UTC, "$lte"=>2015-02-19 17:10:39 UTC}, "loc"=>{"$within"=>{"$polygon"=>[[-122.4310827255249, 37.76572785787643], [-122.4301815032959, 37.75795850991872], [-122.42576122283936, 37.75822994194451], [-122.42477416992188, 37.74781302376846], [-122.42249965667725, 37.748050559413784], [-122.4079942703247, 37.748423828173124], [-122.40408897399902, 37.74950969022236], [-122.40310192108154, 37.751647434568056], [-122.40310192108154, 37.75371725516446], [-122.40344524383545, 37.75673705347827], [-122.40636348724365, 37.75948530210884], [-122.4065351486206, 37.76114777332217], [-122.40559101104736, 37.76297984117803], [-122.40520477294922, 37.7654225277299], [-122.40589141845703, 37.76786513360663], [-122.40812301635742, 37.769357797482144], [-122.41636276245117, 37.769629187677], [-122.42198467254639, 37.77027373539786], [-122.42365837097168, 37.77180027337858], [-122.4310827255249, 37.76572785787643]]}}}, "$explain"=>true, "$orderby"=>{"created_at"=>-1}, "$hint"=>{"created_at"=>-1, "loc.coordinates"=>"2d"}}
@fields=nil>
failed with error 17007: "Unable to execute query: error processing query: ns=snapdate_production.snaps limit=50 skip=0\nTree: $and\n created_at $lte new Date(1424365839454)\n created_at $gte new Date(1424193039454)\n GEO raw = { loc: { $within: { $polygon: [ [ -122.4310827255249, 37.76572785787643 ], [ -122.4301815032959, 37.75795850991872 ], [ -122.4257612228394, 37.75822994194451 ], [ -122.4247741699219, 37.74781302376846 ], [ -122.4224996566772, 37.74805055941378 ], [ -122.4079942703247, 37.74842382817312 ], [ -122.404088973999, 37.74950969022236 ], [ -122.4031019210815, 37.75164743456806 ], [ -122.4031019210815, 37.75371725516446 ], [ -122.4034452438354, 37.75673705347827 ], [ -122.4063634872437, 37.75948530210884 ], [ -122.4065351486206, 37.76114777332217 ], [ -122.4055910110474, 37.76297984117803 ], [ -122.4052047729492, 37.7654225277299 ], [ -122.405891418457, 37.76786513360663 ], [ -122.4081230163574, 37.76935779748214 ], [ -122.4163627624512, 37.769629187677 ], [ -122.4219846725464, 37.77027373539786 ], [ -122.4236583709717, 37.77180027337858 ], [ -122.4310827255249, 37.76572785787643 ] ] } } }\nSort: { created_at: -1 }\nProj: {}\n planner returned error: bad hint"
我的索引:
db.snaps.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "snapdate_production.snaps"
},
{
"v" : 1,
"key" : {
"loc.coordinates" : "2d"
},
"name" : "loc.coordinates_2d",
"ns" : "snapdate_production.snaps"
},
{
"v" : 1,
"key" : {
"created_at" : -1
},
"name" : "created_at_-1",
"ns" : "snapdate_production.snaps"
}
]
根据评论进行更新
评论:db.snaps.ensureIndex({ "created_at" : 1, "loc.coordinates" : "2d" })
irb(main):009:0> @snaps = Snap.where(:created_at=>(2.days.ago..Time.now), :loc => { "$within" => { "$polygon" => hood }}).criteria.extras(:hint => "loc.coordinates_2d_created_at_-1").order_by(:created_at => 'desc').limit(50).skip(offset).explain()
=> {"cursor"=>"BtreeCursor loc.coordinates_2d_created_at_-1", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>74, "nscanned"=>74, "nscannedObjectsAllPlans"=>74, "nscannedAllPlans"=>74, "scanAndOrder"=>true, "indexOnly"=>false, "nYields"=>0, "nChunkSkips"=>0, "millis"=>1, "indexBounds"=>{"loc.coordinates"=>[[{"$minElement"=>1}, {"$maxElement"=>1}]], "created_at"=>[[{"$maxElement"=>1}, {"$minElement"=>1}]]}, "allPlans"=>[{"cursor"=>"BtreeCursor loc.coordinates_2d_created_at_-1", "isMultiKey"=>false, "n"=>4, "nscannedObjects"=>74, "nscanned"=>74, "scanAndOrder"=>true, "indexOnly"=>false, "nChunkSkips"=>0, "indexBounds"=>{"loc.coordinates"=>[[{"$minElement"=>1}, {"$maxElement"=>1}]], "created_at"=>[[{"$maxElement"=>1}, {"$minElement"=>1}]]}}], "server"=>"snapdate:27017", "filterSet"=>false, "stats"=>{"type"=>"SORT", "works"=>82, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>76, "needFetch"=>0, "isEOF"=>1, "forcedFetches"=>0, "memUsage"=>2793, "memLimit"=>33554432, "children"=>[{"type"=>"KEEP_MUTATIONS", "works"=>76, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>71, "needFetch"=>0, "isEOF"=>1, "children"=>[{"type"=>"FETCH", "works"=>76, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>4, "needTime"=>71, "needFetch"=>0, "isEOF"=>1, "alreadyHasObj"=>0, "forcedFetches"=>0, "matchTested"=>4, "children"=>[{"type"=>"IXSCAN", "works"=>75, "yields"=>0, "unyields"=>0, "invalidates"=>0, "advanced"=>74, "needTime"=>1, "needFetch"=>0, "isEOF"=>1, "keyPattern"=>"{ loc.coordinates: \"2d\", created_at: -1.0 }", "isMultiKey"=>0, "boundsVerbose"=>"field #0['loc.coordinates']: [MinKey, MaxKey], field #1['created_at']: [MaxKey, MinKey]", "yieldMovedCursor"=>0, "dupsTested"=>0, "dupsDropped"=>0, "seenInvalidated"=>0, "matchTested"=>0, "keysExamined"=>74, "children"=>[]}]}]}]}}
irb(main):010:0>
答案 0 :(得分:0)
Loc.geo_near([la, lo]).where(loc_field: value)
无法工作,因为geo_near没有返回Mongoid :: Collection对象。另外,正如您所说,搜索地理位置会触及每条记录。
解决方案是首先搜索您的字段,然后搜索您的坐标。
Loc.where(loc_fields: value).geo_near([la, lo])
然后它将首先搜索您的索引字段(更快),最后搜索地理索引。