В изданията на Modern MongoDB можете. Все още не можете "директно" да приложите масив към $concat
, но можете да използвате $reduce
за да работите с елементите на масива и да произведете това:
db.collection.aggregate([
{ "$addFields": {
"values": {
"$reduce": {
"input": "$values",
"initialValue": "",
"in": {
"$cond": {
"if": { "$eq": [ { "$indexOfArray": [ "$values", "$$this" ] }, 0 ] },
"then": { "$concat": [ "$$value", "$$this" ] },
"else": { "$concat": [ "$$value", "_", "$$this" ] }
}
}
}
}
}}
])
Комбинирайки разбира се с $indexOfArray
за да низ "свързване" с "_"
долно черта, когато е "първият" индекс на масива.
Също така на моето допълнително „желание“ беше отговорено с $sum
:
db.collection.aggregate([
{ "$addFields": {
"total": { "$sum": "$items.value" }
}}
])
Този вид се повдига малко като цяло с оператори за агрегиране, които приемат масив от елементи. Разликата тук е, че това означава „масив“ от „агументи“, предоставени в кодираното представяне, за разлика от „елемент на масив“, присъстващ в текущия документ.
Единственият начин, по който наистина можете да направите вида на конкатенация на елементи в рамките на масив, присъстващ в документа, е да направите някаква опция на JavaScript, както в този пример в mapReduce:
db.collection.mapReduce(
function() {
emit( this._id, { "values": this.values.join("_") } );
},
function() {},
{ "out": { "inline": 1 } }
)
Разбира се, ако всъщност не агрегирате нищо, тогава вероятно най-добрият подход е просто да направите тази операция „присъединяване“ в рамките на клиентския си код при последваща обработка на резултатите от заявката. Но ако трябва да се използва за някаква цел в различни документи, mapReduce ще бъде единственото място, където можете да го използвате.
Мога да добавя, че "например" бих искал нещо подобно да работи:
{
"items": [
{ "product": "A", "value": 1 },
{ "product": "B", "value": 2 },
{ "product": "C", "value": 3 }
]
}
И като цяло:
db.collection.aggregate([
{ "$project": {
"total": { "$add": [
{ "$map": {
"input": "$items",
"as": "i",
"in": "$$i.value"
}}
]}
}}
])
Но това не работи по този начин, защото $add
очаква аргументи за разлика от масив от документа. Въздъхни! :(. Част от мотивите "по проект" за това може да се твърди, че "само защото" е масив или "списък" от единични стойности, предавани от резултата от трансформацията, не е "гарантирано", че те са всъщност "валидни" стойности на единичен числов тип, които операторът очаква. Поне не при настоящите внедрени методи за "проверка на типа".
Това означава, че засега все още трябва да направим това:
db.collection.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"total": { "$sum": "$items.value" }
}}
])
Освен това за съжаление няма да има начин да се приложи такъв оператор за групиране за конкатенация на низове.
Така че можете да се надявате на някаква промяна в това или да се надявате на някаква промяна, която позволява променлива с външен обхват да бъде променена в обхвата на $map
операция по някакъв начин. Още по-добре нов $join
операцията също би била добре дошла. Но те не съществуват към момента на писане и вероятно няма да съществуват за известно време.