注意:我正在使用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来做同样的事情?我的计划是使用正则表达式,但似乎到目前为止尚不支持. /p>
具有查找和自定义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 } } } ]);解决方案
最简单的方法是使用3.6中首先可用的$expr,如下所示:
{$match:{$expr:{$eq:[ $second, {$substr:{ $first, 0, {$strLenCP:$second} }} ]}}}这会将字段"second"中的字符串与"first"的前N个字符进行比较,其中N是第二个字符串的长度.如果它们相等,则第一"以第二"开头.
4.2在聚合表达式中增加了对$ regex的支持,但开头要简单得多,并且不需要正则表达式.
note: I'm using Mongodb 4 and I must use aggregation, because this is a step of a bigger aggregation
Problem
How to find in a collection documents that contains fields that starts with value from another field in same document ?
Let's start with this collection:
db.regextest.insert([ {"first":"Pizza", "second" : "Pizza"}, {"first":"Pizza", "second" : "not pizza"}, {"first":"Pizza", "second" : "not pizza"} ])and an example query for exact match:
db.regextest.aggregate([ { $match : { $expr: { $eq: [ "$first" ,"$second" ] } } } ])I will get a single document
{ "_id" : ObjectId("5c49d44329ea754dc48b5ace"), "first" : "Pizza", "second" : "Pizza" }And this is good.
But how to do the same, but with startsWith ? My plan was to use regex but seems that is not supported in aggregation so far.
With a find and a custom javascript function works fine:
db.regextest.find().forEach( function(obj){ if (obj.first.startsWith(obj.second)){ print(obj); } } )And returns correctly:
{ "_id" : ObjectId("5c49d44329ea754dc48b5ace"), "first" : "Pizza", "second" : "Pizza" }How it's possible to get same result with aggregation framework ?
One idea is to use existing aggregation framework pipeline, out to a temp colletion and then run the find above, to get match I'm looking for. This seems to be a workaround, I hope someone have a better idea.
Edit: here the solution
db.regextest.aggregate([{ $project : { "first" : 1, "second" : 1, fieldExists : { $indexOfBytes : ['$first', '$second' , 0] } } }, { $match : { fieldExists : { $gt : -1 } } } ]);解决方案
The simplest way is to use $expr first available in 3.6 like this:
{$match:{$expr:{$eq:[ "$second", {$substr:{ "$first", 0, {$strLenCP:"$second"} }} ]}}}This compare the string in field ‘second’ with the first N characters of ‘first’ where N is the length of second string. If they are equal, then ‘first’ starts with ‘second’.
4.2 adds support for $regex in aggregation expressions, but starts with is much simpler and doesn’t need regular expressions.
更多推荐
使用对字段值的引用进行聚合的MongoDB正则表达式
发布评论