sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur hittar man till mongodb till det sista objektet i en array?

Jag vet att den här frågan är gammal, men jag hittade den på google efter att ha svarat på en liknande ny fråga . Så jag tyckte att det här förtjänade samma behandling.

Du kan undvika prestandaträffen för $where genom att använda aggregat istället:

db.example.aggregate([

    // Use an index, which $where cannot to narrow down
    {$match: { "comments.by": "Abe" }},

    // De-normalize the Array
    {$unwind: "$comments"},

    // The order of the array is maintained, so just look for the $last by _id
    {$group: { _id: "$_id", comments: {$last: "$comment"} }},

    // Match only where that $last comment by `by.Abe`
    {$match: { "comments.by": "Abe" }},

    // Retain the original _id order
    {$sort: { _id: 1 }}

])

Och det borde ringa runt $where eftersom vi kunde begränsa de dokument som hade en kommentar av "Abe" i första hand. Som varnat, $where kommer att testa alla dokument i samlingen och aldrig använda ett index även om ett finns där för att användas.

Naturligtvis kan du också underhålla originaldokumentet med tekniken som beskrivs här likaså, så allt skulle fungera precis som en find() .

Bara en tankeställare för alla som hittar detta.

Uppdatering för moderna MongoDB-versioner

Moderna utgåvor har lagt till $redact pipeline-uttryck samt $arrayElemAt (den senare från och med 3.2, så det skulle vara den minimala versionen här ) som i kombination skulle tillåta ett logiskt uttryck att inspektera det sista elementet i en array utan att bearbeta en $unwind steg:

db.example.aggregate([
  { "$match": { "comments.by": "Abe" }},
  { "$redact": {
    "$cond": {
      "if": {
        "$eq": [
          { "$arrayElemAt": [ "$comments.by", -1 ] },
          "Abe"
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Logiken här görs i jämförelse där $arrayElemAt får det sista indexet för arrayen -1 , som omvandlas till bara en array av värdena i "by" egendom via $map . Detta möjliggör jämförelse av det enstaka värdet mot den önskade parametern, "Abe" .

Eller till och med lite modernare med $expr för MongoDB 3.6 och senare:

db.example.find({
  "comments.by": "Abe",
  "$expr": {
    "$eq": [
      { "$arrayElemAt": [ "$comments.by", -1 ] },
      "Abe"
    ]
  }
})

Detta skulle vara den överlägset mest presterande lösningen för att matcha det sista elementet i en array, och förväntas faktiskt ersätta användningen av $where i de flesta fall och särskilt här.



  1. Nodejs Mongodb uppdaterar flera samlingar

  2. Hur frågar jag bara dokument med den senaste tidsstämpeln från en grupp?

  3. MongoDB Långsam fråga efter ID

  4. Få en distinkt aggregering av ett matrisfält över index