MongoDB不区分大小写的索引"以性能问题开始"

wpf*_*abe 7 mongodb mongodb-query

在发现3.3.11 支持不区分大小写的索引(使用整理)之后,我已经重建了我的数据库,其中包含4000万条记录.替代方案是添加例如特定于不区分大小写的搜索的小写字段并索引那些.

我所做的就是要问的MongoDB在创建时间来支持我的收集,整理在这里建议.所以我这样做是为了使整个集合不区分大小写:

db.createCollection("users", {collation:{locale:"en",strength:1}})
Run Code Online (Sandbox Code Playgroud)

加载集合后,我尝试了直接查询,如:

db.users.find({full_name:"john doe"})
Run Code Online (Sandbox Code Playgroud)

......那些在约10毫秒内返回50个结果.它不区分大小写 - 所以一切都很好.但后来我尝试了类似的东西:

db.users.find({full_name:/^john/})
Run Code Online (Sandbox Code Playgroud)

...要么...

db.users.find({full_name:/^john/i})
Run Code Online (Sandbox Code Playgroud)

......这需要5分钟以上.我很失望.在执行之后explain(),结果显示索引显然正在使用,但查询仍然需要太长时间才能执行.这可归因于错误或不完整的开发版本还是我做了一些根本错误的事情?

当我正在进行"开始"正则表达式搜索时,查询应该是快速的.有任何想法吗?

use*_*723 5

编辑:有一个可行的解决方法。基本上,如果您要搜索的单词是“bob”,您可以搜索 $lt:"boc"(将最后一个字符加一)和 $gte "bob"。这将使用索引。您可以使用我在下面创建的以下函数(警告它不一定没有错误,但几乎可以工作),如下所示:

var searchCriteria = {};
addStartsWithQuery(searchCriteria, "firstName", "bo");
People.find(searchCriteria).then(...);

//searchCriteria will be
/*
{
    $and:[
         {firstName:{$gte:"bo"}},
         {firstName:{$lt:"bp"}}
    ]
}
*/


//now library functions that will automatically generate the correct query and add it to `searchCriteria`.  Of course for complicated queries you may have to modifiy it a bit.
function getEndStr(str) {
    var endStrArr = str.toLocaleLowerCase('en-US').split("");
    for (var i = endStrArr.length - 1; i >= 0; --i) {
        var lastChar = endStrArr[i];
        if(lastChar === "z"){
            return endStrArr.join("") + "zzzzzzzzzzzz";
        }
        var nextChar = String.fromCharCode(lastChar.charCodeAt(0) + 1);
        if (nextChar === ":")
            nextChar = "a";
        if (nextChar !== false) {
            endStrArr[i] = nextChar;
            return endStrArr.join("");
        }
        endStrArr.pop();
    }
}
function addStartsWithQuery(searchCriteria, propertyName, str) {
    if (!(typeof str === 'string') || !str.length)
        return;
    var endStr = getEndStr(str);
    if (endStr) {
        if (!searchCriteria.$and)
            searchCriteria.$and = [];
        searchCriteria.$and.push({
            [propertyName]: {
                $gte: str
            }
        });
        searchCriteria.$and.push({
            [propertyName]: {
                $lt: endStr
            }
        });
    } else {
        searchCriteria[propertyName] = {
            $gte: str
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

事实证明 MongoDB 官方并不支持它!我已经链接到 JIRA 中的一个问题,他们在其中明确说明了这一点。不幸的是,这使得排序规则的用处大大降低。让我们尽快解决这个问题吧!从技术上讲,我注意到即使它使用索引,索引也用作"[\"\", {})",它的索引边界之一,它总是返回索引中的所有项目,因此索引扫描是无用的。查询的下一阶段像平常一样过滤这些结果。

https://jira.mongodb.org/browse/DOCS-9933

投票支持这个问题,让他们解决它! https://jira.mongodb.org/browse/SERVER-29865