MongoDB rimuove gli elementi a seconda di tutti gli altri elementi (ripetizione)

Aug 22 2020

Voglio rimuovere ($ reduce) elementi dai miei oggetti MongoDB con condizione se lo stesso oggetto ha un elemento simile. Il mio oggetto:

  {
    "_id": "5eabf8b144345b36b00bfbaa",
    "ranktime": [
      {
        "pos": "15",
        "datum": "Mon May 01 2020 12:25:14 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "10",
        "datum": "Fri May 05 2020 12:25:14 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "15",
        "datum": "Mon May 01 2020 18:45:27 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "20",
        "datum": "Fri May 05 2020 18:45:27 GMT+0200 (GMT+02:00)",
        "source": "SOURCE1"
      },
      {
        "pos": "10",
        "datum": "Fri May 05 2020 12:25:14 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "15",
        "datum": "Mon May 01 2020 18:45:27 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      }
    ]
  }

Quindi voglio rimuovere la voce in ranktime se ranktime.source == "SOURCE2" e se la data è la stessa dell'oggetto precedente. In realtà devo scorrere i singoli elementi di ranktime. È possibile in MongoDB?

Il risultato atteso sarebbe:

  {
    "_id": "5eabf8b144345b36b00bfbaa",
    "ranktime": [
      {
        "pos": "15",
        "datum": "Mon May 01 2020 12:25:14 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "10",
        "datum": "Fri May 05 2020 12:25:14 GMT+0200 (GMT+02:00)",
        "source": "SOURCE2"
      },
      {
        "pos": "20",
        "datum": "Fri May 05 2020 18:45:27 GMT+0200 (GMT+02:00)",
        "source": "SOURCE1"
      }
    ]
  }

Risposte

1 mickl Aug 22 2020 at 20:34

Quindi, in base al tuo esempio, vuoi generare l'output a ranktime meno che non sia SOURCE2 e la stessa data sia già stata aggiunta all'output (ma solo per SOURCE2).

Puoi usare $reducecome in precedenza ma devi scansionare elementi aggiunti in precedenza che possono essere ottenuti usando $ anyElementTrue operatore e poiché il tuo output contiene il terzo elemento, presumo che la data ripetuta sia una condizione di interruzione solo se è stata aggiunta la stessa data per SORUCE2questo $ filter è necessario anche per preparare il set di messaggi aggiunti in precedenza SOURCE2:

db.col.updateMany({}, [
    {
        $set: {
            ranktime: {
                $reduce: { input: "$ranktime",
                    initialValue: [],
                    in: {
                        $cond: [ { $and: [ 
                                    { "$eq": [ "$$this.source", "SOURCE2" ] },
                                    {
                                        $anyElementTrue: { $map: {
                                                input: { $filter: { input: "$$value", as: "prev", cond: { $eq: { "$$prev.source", "SOURCE2" } } } }, // already added SOURCE2 elements
                                                as: "addedElement",
                                                in: { "$eq": [ { $substr: [ "$$addedElement.datum", 0, 15 ] }, { $substr: [ "$$this.datum", 0, 15 ] } ] } } } } ] }, "$$value", // skip current element ($$this) { $concatArrays: [ "$$value", [ "$$this" ] ] } // add current element to the output
                        ]
                    }
                }
            }
        }
    }
])

Parco giochi Mongo