我希望微调我在Mongo上使用的字符串搜索查询。在SQL Server世界中,我想相信我对索引如何工作以及如何构建适当的索引有一个很好的理解。我尝试用Mongo拍摄它,但是,我不相信我不会以正确的方式进行拍摄。
我的收藏品大约有430万份文件。文档结构如下所示:
{
"_id":{
"$oid":"527027456239d1212c07a621"
},
"ReleaseId":2451,
"Status":"Accepted",
"Title":"Hard Rhythmic Motions",
"Country":"US",
"MasterId":"35976",
"Images":[
{
"Type":"primary",
"URI":"http://api.discogs.com/image/R-2451-1117047026.jpg",
"URI150":"http://api.discogs.com/image/R-150-2451-1117047026.jpg",
"Height":307,
"Width":307
},
{
"Type":"secondary",
"URI":"http://api.discogs.com/image/R-2451-1117047033.jpg",
"URI150":"http://api.discogs.com/image/R-150-2451-1117047033.jpg",
"Height":307,
"Width":307
}
],
"Artists":[
{
"_id":2894,
"Name":"DJ Hyperactive"
}
],
"Formats":[
{
"Name":null,
"Quantity":1
}
],
"Genres":[
"Electronic"
],
"Styles":[
"Hardcore",
"Acid"
]
}
我正在对其中一个顶级文档属性和其中一个嵌套文档属性执行不区分大小写的搜索:
db.releases.find({$or: [{Title: new RegExp('.*mozart.*',"i")},{'Artists.Name': new RegExp('.*mozart.*',"i")}]})
我尝试创建索引;当我执行.getIndexes()
时,我可以看到我创建的索引:
{
"v" : 1,
"key" : {
"Title" : 1,
"Artists.Name" : 1
},
"ns" : "discogs.releases",
"name" : "Title_1_Artists.Name_1"
}
此时我认为我会全力以赴。但是,查询最终需要28到32秒才能执行。我尝试拨打.explain()
以获得更多洞察力:
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 4098,
"nscannedObjects" : 4292400,
"nscanned" : 4292400,
"nscannedObjectsAllPlans" : 4292400,
"nscannedAllPlans" : 4292400,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 29,
"nChunkSkips" : 0,
"millis" : 29958,
"indexBounds" : {
},
"server" : "lambic:27017"
}
根据我对Mongo的有限知识,这看起来像是一个表扫描,这就是查询效果不佳的原因。但是,我不知道如何让这个查询更好!我希望我创建的索引能够覆盖这个查询,但是,情况绝对不是这样。
现在,我要指出的最后一件事是,这肯定不是最强大的服务器。硬件规格(包括CPU和RAM)非常有限。但是,如果我的分析是正确的并且我正在进行表扫描,那么我必须在Mongo端进行一些性能改进。
答案 0 :(得分:0)
全文索引可能就是您所需要的。您还可以在插入文档之前解析文档,并将关键字放在文档中的数组中并索引此数组。
答案 1 :(得分:0)
感谢大家的回复。我想跟进这个问题,因为它有一些投票,并确保将来偶然发现这个页面的人知道我最终做了什么。
全文索引听起来像是一个很好的解决方案。但是,因为这只是我的一个小型项目,我不愿意在架构上投入更多硬件(全文索引需要400万条记录的大量磁盘空间)。
我最终做的是扁平化我的数据结构,以便更容易查询和删除通配符搜索,以便实际上可以使用该新结构上的索引。通过这样做,我可以实现indexOnly查询(虽然性能仍然不是很惊人,但鉴于我的弱硬件堆栈,我发现它足够了。)