【问题标题】:MongoDB unwind multiple empty arraysMongoDB展开多个空数组
【发布时间】:2015-10-21 04:12:59
【问题描述】:

数据库中的示例数据如下所示:

{
'data':
[
    'Log':
    {
        'IP':['8.8.8.8','8.8.4.4'],
        'URL':['www.google.com']
        'Hash' ['d2a12319bf1221ce7681928cc']
    },
    'Log':
    {
        'IP':['1.2.3.4'],
        'URL':['www.cnn.com']
        'Hash' []
    },

]
}

我正在尝试从上述日志列表中汇总唯一 IP、URL 和哈希列表。我当前的查询看起来像这样:

db.loglist.aggregate([{'$match':{'data.Log':{'$exists':true}}},
                {'$unwind':'$data'},
                {'$unwind':'$data.Log.URL'},
                {'$unwind':'$data.Log.Hash'},       
                {'$unwind':'$data.Log.IP'},
                {'$group':{'_id':'$ioc',
                            'FHList':{'$addToSet':'$data.Log.Hash'},
                            'URLList':{'$addToSet':'$data.Log.URL'},
                            'IPList':{'$addToSet':'$data.Log.IP'}}
                }]) 

如果对于每个日志,三个数组中的每个数组中至少有一个元素,则效果很好。但是,当有一个空数组出现在任何一个日志中时。 Mongo 对整个查询返回空。我从一些类似的帖子中发现这是 $unwind 的默认行为。但是使用 $unwind 的标准方法是什么,如果说我们没有“哈希”的结果,我们仍然可以保留“IP”和“URL”的结果。

提前感谢您的任何回答。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    $cond 操作符是这里的主要助手,用一个测试看看数组是否为空,然后用另一个值替换它以便稍后过滤:

    db.loglist.aggregate([
      {"$match":{"data.Log":{"$exists":true}}},
      {"$unwind":"$data"},
      { "$project": {
         "ioc": 1,
         "data": {
             "Log": {
                "IP": { "$cond": [
                  { "$ne": [ "$IP", [] ] },
                  "$IP",
                  [false]
                ]},
                "URL": { "$cond": [
                  { "$ne": [ "$URL", [] ] },
                  "$URL",
                  [false]
                ]},
                "Hash": { "$cond": [
                  { "$ne": [ "$Hash", [] ] },
                  "$Hash",
                  [false]
                ]}
             }
         }
      }}
      {"$unwind":"$data.Log.URL"},
      {"$unwind":"$data.Log.Hash"},       
      {"$unwind":"$data.Log.IP"},
      {"$group":{
          "_id":"$ioc",
          "FHList":{"$addToSet":"$data.Log.Hash"},
          "URLList":{"$addToSet":"$data.Log.URL"},
          "IPList":{"$addToSet":"$data.Log.IP"}
      }},
      { "$project": {
          "FHList":{ "$setDifference": ["$FHList", [false]] },
          "URLList":{ "$setDifference": ["$URList", [false]] },
          "IPList":{ "$setDifference": ["$IPList", [false]] }
      }}
    ])  
    

    一旦它构建的集合,不需要的值就会被过滤掉。

    如果您的 MongoDB 版本低于 2.6 并且您没有$setDifference,那么您可以在再次展开后进行过滤,假设此处没有结果数组应为空:

    db.loglist.aggregate([
      {"$match":{"data.Log":{"$exists":true}}},
      {"$unwind":"$data"},
      { "$project": {
         "ioc": 1,
         "data": {
             "Log": {
                "IP": { "$cond": [
                  { "$ne": [ "$IP", [] ] },
                  "$IP",
                  [false]
                ]},
                "URL": { "$cond": [
                  { "$ne": [ "$URL", [] ] },
                  "$URL",
                  [false]
                ]},
                "Hash": { "$cond": [
                  { "$ne": [ "$Hash", [] ] },
                  "$Hash",
                  [false]
                ]}
             }
         }
      }}
      {"$unwind":"$data.Log.URL"},
      {"$unwind":"$data.Log.Hash"},       
      {"$unwind":"$data.Log.IP"},
      {"$group":{
          "_id":"$ioc",
          "FHList":{"$addToSet":"$data.Log.Hash"},
          "URLList":{"$addToSet":"$data.Log.URL"},
          "IPList":{"$addToSet":"$data.Log.IP"}
      }},
      { "$unwind": "$FHList" },
      { "$match": { "FHList": { "$ne": false } }},
      { "$unwind": "$URLList" },
      { "$match": { "URLList": { "$ne": false } }},
      { "$unwind": "$IPList" },
      { "$match": { "IPList": { "$ne": false } }},
      { "$group": {
          "_id": "$_id",
          "FHList":{ "$addToSet":"$FHList" },
          "URLList":{ "$addToSet":"$URLList" },
          "IPList":{ "$addToSet":"$IPList" }
      }}
    ])  
    

    如果你的分组数组是空的,那么第二种形式很棘手,但仍然可能。

    【讨论】:

      猜你喜欢
      • 2017-01-15
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 2015-09-12
      • 2022-01-10
      • 1970-01-01
      • 2015-02-25
      • 2019-04-10
      相关资源
      最近更新 更多