2015-07-29 4 views
1

Выборочные данные в базе данных выглядит следующим образом:MongoDB размотать множественные пустые массивы

{ 
'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 и Hash из приведенного выше списка журналов. Мой текущий запрос выглядит н так:

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 возвращает пустой для всего запроса. Я понял, что это поведение по умолчанию для $ relind from несколько похожих сообщений. Но каков стандартный способ использования $ unwind then, если, скажем, у нас нет результатов для «Hash», мы все равно можем сохранить результаты для «IP» и «URL».

Заранее благодарим за любой ответ.

ответ

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]] } 
    }} 
]) 

После того, как установить его contructed нежелательный значение отфильтровывается.

Если ваша версия 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" } 
    }} 
]) 

Если ваши сгруппированных массивы были пусты, но во второй форме это сложно, но все же возможно.

+0

Это работает! Большое спасибо. –

Смежные вопросы