注意:我使用的是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 做同样的事情呢?我的计划是使用正则表达式,但似乎是 not supported in aggregation so far .
使用查找和自定义 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
}
}
}
]);
最佳答案
最简单的方法是使用 $expr
,首先在 3.6 中可用,如下所示:
{
$match: {
$expr: {
$eq: [
'$second',
{
$substr: ['$first', 0, { $strLenCP: '$second' }]
}
]
}
}
}
这会将字段 second
中的字符串与 first
的前 N 个字符进行比较,其中 N 是第二个字符串的长度。如果它们相等,则 first
以 second
开始。
4.2 在聚合表达式中添加了对$regex
的支持,但是开头更简单,不需要正则表达式。
关于聚合中的 Mongodb 正则表达式使用对字段值的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54365355/