首页 > 解决方案 > 使用对字段值的引用进行聚合中的 Mongodb 正则表达式

问题描述

注意:我使用的是 Mongodb 4,我必须使用聚合,因为这是更大聚合的一步

问题

如何在包含以同一文档中另一个字段的值开头的字段的集合文档中查找?

让我们从这个集合开始:

db.regextest.insert([
{"first":"Pizza", "second" : "Pizza"},
{"first":"Pizza", "second" : "not pizza"},
{"first":"Pizza", "second" : "not pizza"}
])

以及完全匹配的示例查询:

db.regextest.aggregate([
{
    $match :  { $expr: { $eq: [ "$first" ,"$second" ] }   }    }
])

我会得到一份文件

{
    "_id" : ObjectId("5c49d44329ea754dc48b5ace"),
    "first" : "Pizza",    "second" : "Pizza"
}

这很好。

但是如何做同样的事情,但使用 startsWith ?我的计划是使用正则表达式,但目前似乎不支持聚合

使用 find 和自定义 javascript 函数可以正常工作:

db.regextest.find().forEach(
    function(obj){
        if (obj.first.startsWith(obj.second)){
            print(obj);
        }
    }
)

并正确返回:

{
    "_id" : ObjectId("5c49d44329ea754dc48b5ace"),
    "first" : "Pizza",
    "second" : "Pizza"
}

如何使用聚合框架获得相同的结果?

一个想法是使用现有的聚合框架管道,到一个临时集合,然后运行上面的查找,以获得我正在寻找的匹配。这似乎是一种解决方法,我希望有人有更好的主意。

编辑:这里是解决方案

db.regextest.aggregate([{
        $project : {
            "first" : 1,
            "second" : 1,
            fieldExists : {
                $indexOfBytes : ['$first', '$second' , 0]
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }
]);

标签: mongodbaggregation-framework

解决方案


最简单的方法是使用$expr3.6 中的 first available ,如下所示:

{$match:{$expr:{$eq:[
    “$second”,
    {$substr:{
        “$first”,
        0,
        {$strLenCP:”$second”}
    }}
]}}}

这会将字段“second”中的字符串与“first”的前 N ​​个字符进行比较,其中 N 是第二个字符串的长度。如果它们相等,则“第一”以“第二”开头。

4.2 在聚合表达式中增加了对 $regex 的支持,但开头更简单,不需要正则表达式。


推荐阅读