sql >> Database >  >> NoSQL >> MongoDB

Concat-reeks per groep

U kunt het doen met het aggregatieraamwerk als een bewerking in twee stappen. Dat is om eerst de items in een array te verzamelen via $push binnen een $group pijplijn, en vervolgens om $concat te gebruiken met $reduce op de geproduceerde array in uiteindelijke projectie:

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

We passen ook $cond toe hier om te voorkomen dat een lege tekenreeks wordt samengevoegd met een komma in de resultaten, zodat het meer op een gescheiden lijst lijkt.

Ter info Er is een JIRA-probleem SERVER-29339 die wel vraagt ​​om $reduce te implementeren als een accumulator-expressie om direct gebruik in een $group toe te staan pijplijn stadium. Zal waarschijnlijk niet snel gebeuren, maar in theorie zou het $push in het bovenstaande en maak van de operatie een enkele pijplijnfase. Voorbeeld voorgestelde syntaxis betreft het JIRA-probleem.

Als je geen $reduce hebt (vereist MongoDB 3.4 ) en vervolgens de cursor te verwerken:

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

Wat vervolgens leidt tot het andere alternatief om dit te doen met behulp van mapReduce als het echt moet:

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

Wat natuurlijk resulteert in de specifieke mapReduce vorm van _id en value als de set sleutels, maar het is in feite de uitvoer.

We gebruiken [].concat.apply([],values.map(...)) omdat de uitvoer van de "reducer" een "gescheiden tekenreeks" kan zijn omdat mapReduce werkt incrementeel met grote resultaten en daarom kan de uitvoer van het verloopstuk "invoer" worden op een andere pas. We moeten dus verwachten dat dit kan gebeuren en het dienovereenkomstig behandelen.



  1. MongoDB - Aggregatieraamwerk (totaal aantal)

  2. Python + Memcached:efficiënte caching in gedistribueerde applicaties

  3. In MongoDB, hoe een query uit te voeren op basis van of een tekenreeksveld een ander bevat?

  4. MongoDB / Express - Van database wisselen na verbinding via connect()