MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Concat String по група

Можете да го направите с рамката за агрегиране като операция в "две стъпки". Което е първо да натрупате елементите в масив чрез $push с $group тръбопровод и след това да използвате $concat с $reduce върху произведения масив в крайната проекция:

db.collection.aggregate([
  { "$group": {
    "_id": "$tag_id",
    "client_id": { "$push": "$client_id" }
  }},
  { "$addFields": {
    "client_id": {
      "$reduce": {
        "input": "$client_id",
        "initialValue": "",
        "in": {
          "$cond": {
            "if": { "$eq": [ "$$value", "" ] },
            "then": "$$this",
            "else": {
              "$concat": ["$$value", ",", "$$this"]
            }
          }
        }
      }
    }
  }}
])

Също така прилагаме $cond тук, за да избегнете свързването на празен низ със запетая в резултатите, така че да изглежда по-скоро като списък с разделители.

FYI Има проблем с JIRA SERVER-29339 което изисква $reduce да се внедри като акумулаторен израз за да разрешите използването му директно в $group етап на тръбопровод. Няма вероятност да се случи скоро, но теоретично ще замени $push в горното и направете операцията единичен тръбопроводен етап. Примерният предложен синтаксис е по въпроса с JIRA.

Ако нямате $reduce (изисква MongoDB 3.4), след това просто обработете курсора след това:

db.collection.aggregate([
  { "$group": {
    "_id": "$tag_id",
    "client_id": { "$push": "$client_id" }
  }},
]).map( doc =>
  Object.assign(
    doc,
   { "client_id": doc.client_id.join(",") }
  )
)

Което след това води до другата алтернатива да направите това с помощта на mapReduce ако наистина трябва:

db.collection.mapReduce(
  function() {
    emit(this.tag_id,this.client_id);
  },
  function(key,values) {
    return [].concat.apply([],values.map(v => v.split(","))).join(",");
  },
  { "out": { "inline": 1 } }
)

Което разбира се извежда в конкретния mapReduce под формата на _id и value като набор от ключове, но основно е изходът.

Използваме [].concat.apply([],values.map(...)) защото изходът на "редуцента" може да бъде "разделен низ", защото mapReduce работи постепенно с големи резултати и следователно изходът на редуктора може да стане "вход" при друго преминаване. Така че трябва да очакваме, че това може да се случи и да го третираме по съответния начин.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Верижно базирано на времето сортиране и проблем с ограничаване

  2. Използване на множество бази данни Mongodb с Meteor.js

  3. създаване на група и анализиране на данни от списък с масиви в birt

  4. как да запазя dataframe в mongodb с помощта на pyspark?

  5. Защо се добавя _id с ObjectID, когато се използва $push на MongoDB за добавяне на нов обект към масив?