sql >> Database teknologi >  >> NoSQL >> MongoDB

Konkret streng efter gruppe

Du kan gøre det med aggregeringsrammen som en "to-trins" operation. Hvilket er først at akkumulere elementerne til et array via $push inden for en $group pipeline og derefter bruge $concat med $reduce på det producerede array i endelig projektion:

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

Vi anvender også $cond her for at undgå at sammenkæde en tom streng med et komma i resultaterne, så det ligner mere en afgrænset liste.

FYI Der er et JIRA-problem SERVER-29339 som beder om $reduce skal implementeres som et akkumulatorudtryk for at tillade dets brug direkte i en $group pipeline fase. Det er ikke sandsynligt, at det snart vil ske, men det ville teoretisk set erstatte $push i ovenstående og gør operationen til et enkelt rørledningstrin. Eksempel på foreslået syntaks er på JIRA-spørgsmålet.

Hvis du ikke har $reduce (kræver MongoDB 3.4) så skal du bare efterbehandle markøren:

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

Hvilket så fører til det andet alternativ at gøre dette ved at bruge mapReduce hvis du virkelig skal:

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

Hvilket selvfølgelig udsender i den specifikke mapReduce form for _id og value som et sæt nøgler, men det er dybest set outputtet.

Vi bruger [].concat.apply([],values.map(...)) fordi outputtet af "reduceren" kan være en "separeret streng", fordi mapReduce arbejder trinvist med store resultater, og derfor kan output fra reduceren blive "input" på et andet gennemløb. Så vi skal forvente, at dette kan ske og behandle det derefter.



  1. Hvordan får man en forklaring for en MongoDB-tælling?

  2. Mongodb dot notation jokertegn?

  3. MongoDB 3.0.5 fejl:symbolopslagsfejl:udefineret symbol:FIPS_mode_set

  4. Introduktion til Redis Cluster Sharding – fordele, begrænsninger, implementering og klientforbindelser