Mongodb聚合匹配以使用字段值结束

时间:2019-01-29 15:36:31

标签: mongodb aggregation-framework

注意:我正在使用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"
}

这很好。

但是如何使用endsWith做同样的事情?

我在这里对start with使用indexOfBytes提出了另一个问题。但是indexOf只返回第一个匹配项,而不返回最后一个匹配项

编辑:我找到了一个可以接受的答案(有很多自定义逻辑,我希望Mongodb团队可以解决这个问题),这里是解决方案:

db.regextest.aggregate([
    {
        $addFields : {
            "tmpContains" : { $indexOfBytes: [ "$first", { $ifNull : [ "$second" , 0] }  ] }
        }
    },
    {
        $match: { "tmpContains" : { $gt : -1 } }
    },
    {
        $addFields : {
            "firstLen" : { $strLenBytes: "$first" }
        }
    },
    {
        $addFields : {
            "secondLen" : { $strLenBytes: "$second" }
        }
    },
    {
        $addFields : {
            "diffLen" : { $abs: { $subtract : [ "$firstLen", "$secondLen"] } }
        }
    },
    {
        $addFields : {
           "res" : { $substr:  [ "$first", "$diffLen", "$firstLen"] }
        }
    },
    {
        $match : { $expr : { $eq: [ "$res" , "$second" ] }}
    }
])

1 个答案:

答案 0 :(得分:1)

您知道两个字段的长度($strLenBytes),可以使用$substr获取n字段的最后second个字符并将其与{{1 }}字段,尝试:

first

以上汇总将为您提供相同的结果,因为字符串比较在MongoDB中区分大小写。要解决此问题,您可以将$toLower运算符同时应用于db.regextest.aggregate([ { $match: { $expr: { $eq: [ "$first", { $let: { vars: { firstLen: { $strLenBytes: "$first" }, secondLen: { $strLenBytes: "$second" } }, in: { $substr: [ "$second", { $subtract: [ "$$secondLen", "$$firstLen" ] }, "$$firstLen" ] } } } ] } } } ]) 和计算出的$first子字符串,请尝试:

$second