【问题标题】:Use $Redact with a regular expression将 $Redact 与正则表达式一起使用
【发布时间】:2018-09-01 01:59:25
【问题描述】:

在聚合管道中,我试图根据该对象中字段的值过滤对象数组的某些元素。

假设我有这个条目:

 {
   "_id": "5b8911d346d19645f8a66bf4",
   "title": "test task",
   "creation_date": "2018-08-31T10:00:51.598Z",
   "logs": [
    {
       "_id": "5b89126c46d19645f8a66bfb",
       "content": "Running"
    },
    {
       "_id": "5b89128646d19645f8a66bfd",
       "content": "Stopping"
    },
    {
       "_id": "5b89128646d19645f8a66bfd",
       "content": "Stopped"
    }
   ]
 }

我的目标是只过滤内容中包含stop 字的日志:

 {
   "_id": "5b8911d346d19645f8a66bf4",
   "title": "test task",
   "creation_date": "2018-08-31T10:00:51.598Z",
   "logs": [
    {
       "_id": "5b89128646d19645f8a66bfd",
       "content": "Stopping"
    },
    {
       "_id": "5b89128646d19645f8a66bfd",
       "content": "Stopped"
    }
   ]
 }

我尝试使用$redact来消除所有不包含stop字样的日志:

$redact: {
   $cond: {
      if: { $match: { "logs.content": { $regex: "stop", $options: 'i' }}},
      then: "$$KEEP",
      else: "$$PRUNE"
   }
}

但我不断收到错误消息:

Unrecognized expression '$match'

【问题讨论】:

标签: mongodb aggregation-framework


【解决方案1】:

你可以试试下面的聚合

db.collection.aggregate([
  { "$addFields": {
    "logs": {
      "$filter": {
        "input": "$logs",
        "cond": {
          "$ne": [
            { "$indexOfBytes": [
              { "$toUpper": "$$this.content" },
              { "$toUpper": "stop" }
            ]},
            -1
          ]
        }
      }
    }
  }}
])

输出

[
  {
    "_id": "5b8911d346d19645f8a66bf4",
    "creation_date": "2018-08-31T10:00:51.598Z",
    "logs": [
      {
        "_id": "5b89128646d19645f8a66bfd",
        "content": "Stopping"
      },
      {
        "_id": "5b89128646d19645f8a66bfd",
        "content": "Stopped"
      }
    ],
    "title": "test task"
  }
]

【讨论】:

    【解决方案2】:

    根据您的要求,以下查询正在运行并且经过适当测试

    db.users.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $unwind: {
                path : "$logs",
                preserveNullAndEmptyArrays : true // optional
            }
        },
    
        // Stage 2
        {
            $group: {
                      _id: "$_id",
                      "title" :{$last:"$title"} , 
                          "creation_date" :{$last:"$creation_date"},
                      logs: {
                        $push: {
                          $cond: [ {$or:[{"$eq":[{ "$substr": [ "$logs.content", 0, 4 ] }, "Stop"]},{"$eq":[{ "$substr": [ "$logs.content", 0, 4 ] }, "stop"]}]},{"_id":"$logs._id","content":"$logs.content"},null]
                          }
                        }
                      }
    
    
        },
    
        // Stage 3
        {
            $project: {
                logs: {
                        $filter: {
                           input: "$logs",
                           as: "log",
                           cond: { $ne: [ "$$log", null ] }
                        }
                     }
            }
        },
    
    ]
    
    // Created with Studio 3T, the IDE for MongoDB - https://studio3t.com/
    

    );

    【讨论】:

    • 感谢您的回答。我预计这个解决方案会出现一个问题:如果第 2 阶段没有返回任何结果怎么办?在这种情况下,聚合也不会返回父文档
    • 'stop' 关键字和所有值都是为了示例而给出的。 content 字段可以包含任何值,并且搜索值可以是除“停止”之外的任何其他值。我相信长度为4substr不能应用于过滤器的任何情况
    • 检查我有更新的查询我认为它适用于所有场景
    猜你喜欢
    • 2015-12-18
    • 2016-12-29
    • 2011-06-19
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    相关资源
    最近更新 更多