MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Concat Ciąg według grupy

Możesz to zrobić za pomocą struktury agregacji jako operacji „dwuetapowej”. Oznacza to najpierw zgromadzenie elementów w tablicy za pomocą $push z $group potoku, a następnie użyć $concat z $reduce na wytworzonej tablicy w rzucie końcowym:

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

Stosujemy również $cond tutaj, aby uniknąć łączenia pustego ciągu z przecinkiem w wynikach, dzięki czemu wygląda bardziej jak lista rozdzielana.

FYI Wystąpił problem z JIRA SERVER-29339 który prosi o $reduce do zaimplementowania jako wyrażenie akumulacyjne aby umożliwić jego użycie bezpośrednio w $group etap rurociągu. Prawdopodobnie nie nastąpi to w najbliższym czasie, ale teoretycznie zastąpiłoby to $push w powyższym i uczynić operację jednym etapem rurociągu. Przykładowa proponowana składnia dotyczy kwestii JIRA.

Jeśli nie masz $reduce (wymaga MongoDB 3.4 ), a następnie po prostu przetwórz kursor:

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

Co następnie prowadzi do innej alternatywy wykonania tego przy użyciu mapReduce jeśli naprawdę musisz:

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

Który oczywiście wyprowadza w konkretnym mapReduce forma _id i value jako zestaw kluczy, ale w zasadzie jest to wynik.

Używamy [].concat.apply([],values.map(...)) ponieważ wyjście „reduktora” może być „rozgraniczonym ciągiem”, ponieważ mapReduce działa przyrostowo z dużymi wynikami i dlatego wyjście reduktora może stać się "wejściem" w innym przejściu. Musimy więc oczekiwać, że tak się stanie i odpowiednio to potraktować.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Zapytanie mongodb, aby zwrócić dokumenty utworzone dzisiaj

  2. Nazwa dynamicznej kolekcji Nodejs mongodb

  3. Nie można użyć BsonIgnoreIfDefault dla właściwości typu long

  4. Filtruj tablicę za pomocą operatora $in na etapie $project

  5. Jak zmienić nazwę pola w tablicy za pomocą poleceń bazy danych?