【问题标题】:Mongo aggregation with relevance match multiple fields具有相关性的Mongo聚合匹配多个字段
【发布时间】:2013-12-28 10:43:09
【问题描述】:

this 其他问题开始,我正在尝试根据用户的搜索输入收集包含关键字的条目。这是针对客户站点的,架构设置如下:

{
    fid: Number, // unique id for client's internal purposes
    email: String,
    password: String, // hashed
    name: {
        first: String,
        last: String
    },
    group: {
        name: String,
        description: String,
        type: String
    },
    bio: {
        short: String,
        long: String
    }
}

这是我的查询:

db.users.aggregate(
    [{
        $match: {
            $or: [
                {
                    'name.first': {
                        $regex: userInput,
                        $options: 'i'
                     }
                },
                {
                    'name.last': {
                        $regex: userInput,
                        $options: 'i'
                    }
                },
                {
                    'bio.short': {
                        $regex: userInput,
                        $options: 'i'
                    }
                },
                {
                    'bio.long': {
                        $regex: userInput,
                        $options: 'i'
                    }
                }
            ]
        },
        { $unwind: { '$name.first', '$name.last', '$bio.short', '$bio.long' } },
        {
            $match: {
                $or: [
                    {
                        'name.first': {
                            $regex: userInput,
                            $options: 'i'
                         }
                    },
                    {
                        'name.last': {
                            $regex: userInput,
                            $options: 'i'
                        }
                    },
                    {
                        'bio.short': {
                            $regex: userInput,
                            $options: 'i'
                        }
                    },
                    {
                        'bio.long': {
                            $regex: userInput,
                            $options: 'i'
                        }
                    }
                ]
            }
        },
        { $group: { _id: '$fid', hitCount: { $sum: 1 } } },
        { $sort: { hitCount: -1 } }
    }]
);

对于这种类型的查询,我不断收到意外的逗号或结束大括号。我似乎找不到我做错了什么(我已将我的 mongodb.conf 详细日志记录提高到 11)。我在哪里错了,我什至在正确的道路上吗?我想返回每个条目(对象?)以及除密码字段之外的所有信息,我该如何过滤掉它?

【问题讨论】:

    标签: mongodb mongoose


    【解决方案1】:

    case-insensitive $regex 中使用多个$or 子句不会非常高效——尤其是当您要搜索大量数据时。 MongoDB(从 2.4 开始)无法有效地使用不区分大小写的正则表达式的索引(标准索引区分大小写),并且在每个字段中的任何位置进行匹配对于大字符串来说都是代价高昂的比较。 $or 子句是独立执行的,因此您最好在每个字段上都有一个索引(以避免完整的集合扫描),不区分大小写的 $regex 比较仍将是完整的索引扫描。

    对于这个用例,更好的方法是使用 MongoDB 2.4+ 中可用的 text indexes。文本索引不区分大小写,包括language-based word stemming,可以包括多个文本字段,并且总是按照相关性排序的顺序返回结果。您也可以adjust the relative weights为被索引的字段。

    值得注意的是stemming 与使用正则表达式不同。如果您想匹配单词,词干提取有助于减少到通用语言根(即“running”匹配“run”)。

    如果您要匹配姓名,您可能需要一种基于相似性或字符转置的模糊匹配方法。有关匹配名称的几种方法的优秀文章,请参阅Efficient Techniques for Fuzzy and Partial matching in mongoDB

    【讨论】:

    • 我还要注意,文本搜索功能最早是在 MongoDB 2.4 中引入的,目前必须be explicitly enabled。在即将发布的 MongoDB 2.6 版本中,将默认启用文本搜索。 MongoDB 手册指出了一些usage caveats,例如更大的text 索引和词干提取的潜在性能成本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 2018-02-03
    相关资源
    最近更新 更多