2017-01-15 4 views
1

В настоящее время я изменяю схему, и мне нужно сделать относительно тривиальное преобразование с использованием структуры агрегации и bulkWrite.Инкапсуляция/преобразование массива в массив объектов

Я хочу, чтобы иметь возможность принять этот массив:

{ 
    ..., 
    "images" : [ 
     "http://example.com/...", 
     "http://example.com/...", 
     "http://example.com/..." 
    ] 
} 

и агрегат для подобного массива, где исходное значение инкапсулированных:

{ 
    ..., 
    "images" : [ 
     {url: "http://example.com/..."}, 
     {url: "http://example.com/..."}, 
     {url: "http://example.com/..."} 
    ] 
} 

Это медленно запроса работает, но смешно дорого раскрутить целую коллекцию.

[ 
    { 
     $match: {} 
    }, 
    { 
     $unwind: { 
      path : "$images", 
     } 
    }, 
    { 
     $group: { 
      _id: "$_id", 
      images_2: {$addToSet: {url: "$images"}} 
     } 
    }, 
] 

Как это может быть достигнуто с project или какой-либо другой дешевой агрегации?

ответ

2

$map выражение должно сделать работу, попробуйте следующее:

db.col.aggregate([ 
    { 
    $project: { 
     images: { 
     $map: { 
      input: '$images', 
      as: 'url', 
      in: { 
      url: '$$url' 
      } 
     } 
     } 
    } 
    } 
]); 
1

Вам не нужно использовать метод bulkWrite() для этого.

Вы можете использовать оператор агрегации $map для применения выражения к каждому элементу элемента в вашем массиве.

Здесь выражение просто создает новый объект, в котором значением является элемент в массиве.

let mapExpr = { 
    "$map": { 
     "input": "$images", 
     "as": "imageUrl", 
     "in": { "url": "$$imageUrl } 
    } 
}; 

Наконец, вы можете использовать оператор конвейера $out агрегацию перезаписать вашу коллекцию или записать результат в другой коллекции.

Конечно, $map не является оператором трубопровода агрегации, поэтому это означает, что выражение $map должно использоваться на стадии трубопровода.

То, как вы это делаете, зависит от вашей версии MongoDB.

Лучший способ в MongoDB 3.4 с использованием $addFields изменить значение поля «изображения» в документе.

db.collection.aggregate([ 
    { "$addFields": { "images": mapExpr }}, 
    { "$out": "collection } 
]) 

От MongoDB 3.2 назад, вы должны использовать этап $project трубопровода, но вы также должны включать все другие поля вручную в документе

db.collection.aggregate([ 
    { "$project": { "images": mapExpr } }, 
    { "$out": "collection } 
])