Ve verzích Modern MongoDB můžete. Stále nemůžete "přímo" použít pole na $concat
, ale můžete použít $reduce
pracovat s prvky pole a vytvořit toto:
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" ] }
}
}
}
}
}}
])
Samozřejmě v kombinaci s $indexOfArray
aby ne "concatenate" s "_"
podtržítko, když je to "první" index pole.
Také moje další "přání" bylo zodpovězeno $sum
:
db.collection.aggregate([
{ "$addFields": {
"total": { "$sum": "$items.value" }
}}
])
Tento druh se obecně trochu zvyšuje s agregačními operátory, které berou řadu položek. Rozdíl je v tom, že to znamená „pole“ „agumentů“ poskytnutých v kódované reprezentaci na rozdíl od „prvku pole“ přítomného v aktuálním dokumentu.
Jediný způsob, jak můžete skutečně provést druh zřetězení položek v poli přítomné v dokumentu, je provést nějakou volbu JavaScriptu, jako v tomto příkladu v mapReduce:
db.collection.mapReduce(
function() {
emit( this._id, { "values": this.values.join("_") } );
},
function() {},
{ "out": { "inline": 1 } }
)
Samozřejmě, pokud ve skutečnosti nic neagregujete, pak možná nejlepším přístupem je jednoduše provést operaci „spojení“ ve vašem klientském kódu při následném zpracování výsledků dotazu. Ale pokud je třeba jej použít k nějakému účelu napříč dokumenty, pak mapReduce bude jediným místem, kde jej můžete použít.
Mohl bych dodat, že „například“ bych byl rád, kdyby něco takového fungovalo:
{
"items": [
{ "product": "A", "value": 1 },
{ "product": "B", "value": 2 },
{ "product": "C", "value": 3 }
]
}
A v souhrnu:
db.collection.aggregate([
{ "$project": {
"total": { "$add": [
{ "$map": {
"input": "$items",
"as": "i",
"in": "$$i.value"
}}
]}
}}
])
Ale takto to nefunguje, protože $add
očekává argumenty na rozdíl od pole z dokumentu. Povzdech! :(. Část zdůvodnění „by design“ by mohla být argumentována tím, že „jen proto, že“ jde o pole nebo „seznam“ singulárních hodnot předávaných z výsledku transformace, není „zaručeno“, že jsou skutečně „platné“ singulární číselné hodnoty typu, které operátor očekává. Alespoň ne u současných implementovaných metod „kontroly typu“.
To znamená, že zatím musíme udělat toto:
db.collection.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"total": { "$sum": "$items.value" }
}}
])
A také by bohužel neexistoval způsob, jak použít takový seskupovací operátor ke zřetězení řetězců.
Můžete tedy doufat v nějakou změnu v tomto nebo doufat v nějakou změnu, která umožní změnit externě vymezenou proměnnou v rámci $map
nějakým způsobem provozovat. Ještě lepší nový $join
operace by byla také vítána. Ty však v době psaní neexistují a pravděpodobně ještě nějakou dobu nebudou.