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

Конкатениране на низови стойности в масив в едно поле в MongoDB

В изданията на Modern MongoDB можете. Все още не можете "директно" да приложите масив към $concat , но можете да използвате $reduce за да работите с елементите на масива и да произведете това:

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

Комбинирайки разбира се с $indexOfArray за да низ "свързване" с "_" долно черта, когато е "първият" индекс на масива.

Също така на моето допълнително „желание“ беше отговорено с $sum :

db.collection.aggregate([
  { "$addFields": {
    "total": { "$sum": "$items.value" }
  }}
])

Този вид се повдига малко като цяло с оператори за агрегиране, които приемат масив от елементи. Разликата тук е, че това означава „масив“ от „агументи“, предоставени в кодираното представяне, за разлика от „елемент на масив“, присъстващ в текущия документ.

Единственият начин, по който наистина можете да направите вида на конкатенация на елементи в рамките на масив, присъстващ в документа, е да направите някаква опция на JavaScript, както в този пример в mapReduce:

db.collection.mapReduce(
    function() {
        emit( this._id, { "values": this.values.join("_") } );
    },
    function() {},
    { "out": { "inline": 1 } }
)

Разбира се, ако всъщност не агрегирате нищо, тогава вероятно най-добрият подход е просто да направите тази операция „присъединяване“ в рамките на клиентския си код при последваща обработка на резултатите от заявката. Но ако трябва да се използва за някаква цел в различни документи, mapReduce ще бъде единственото място, където можете да го използвате.

Мога да добавя, че "например" бих искал нещо подобно да работи:

{
    "items": [
        { "product": "A", "value": 1 },
        { "product": "B", "value": 2 },
        { "product": "C", "value": 3 }
    ]
}

И като цяло:

db.collection.aggregate([
    { "$project": {
        "total": { "$add": [
            { "$map": {
                "input": "$items",
                "as": "i",
                "in": "$$i.value"
            }}
        ]}
    }}
])

Но това не работи по този начин, защото $add очаква аргументи за разлика от масив от документа. Въздъхни! :(. Част от мотивите "по проект" за това може да се твърди, че "само защото" е масив или "списък" от единични стойности, предавани от резултата от трансформацията, не е "гарантирано", че те са всъщност "валидни" стойности на единичен числов тип, които операторът очаква. Поне не при настоящите внедрени методи за "проверка на типа".

Това означава, че засега все още трябва да направим това:

db.collection.aggregate([
   { "$unwind": "$items" },
   { "$group": {
       "_id": "$_id",
        "total": { "$sum": "$items.value" }
   }}
])

Освен това за съжаление няма да има начин да се приложи такъв оператор за групиране за конкатенация на низове.

Така че можете да се надявате на някаква промяна в това или да се надявате на някаква промяна, която позволява променлива с външен обхват да бъде променена в обхвата на $map операция по някакъв начин. Още по-добре нов $join операцията също би била добре дошла. Но те не съществуват към момента на писане и вероятно няма да съществуват за известно време.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как мога да настроя MongoDB на сървър Node.js, използвайки node-mongodb-native в EC2 среда?

  2. Как да генерирате уникален идентификатор на обект в mongodb

  3. MongoDB $indexOfBytes

  4. Свързване и създаване на MongoDB Joins с помощта на SQL:Част 3

  5. MongoDB – Донесете свои собствени SSL сертификати