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

Как да намеря в mongodb до последния елемент от масив?

Знам, че този въпрос е стар, но го намерих в Google, след като отговорих на подобен нов въпрос . Така че реших, че това заслужава същото отношение.

Можете да избегнете удара в производителността на $where чрез използване на aggregate вместо това:

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

])

И това трябва да обикаля около $where тъй като успяхме да стесним обхвата на документите, които има коментар на "Абе" на първо място. Както беше предупредено, $where ще тества всеки документ в колекцията и никога няма да използва индекс, дори ако има такъв за използване.

Разбира се, можете също да поддържате оригиналния документ, като използвате техниката, описана тук също така, така че всичко ще работи точно като find() .

Само храна за размисъл за всеки, който открие това.

Актуализация за модерни версии на MongoDB

Съвременните версии са добавили $redact тръбопроводен израз, както и $arrayElemAt (последното от 3.2, така че това ще бъде минималната версия тук), което в комбинация ще позволи на логически израз да инспектира последния елемент от масив, без да обработва $unwind етап:

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

Логиката тук се прави в сравнение, когато $arrayElemAt получава последния индекс на масива -1 , който се трансформира само в масив от стойностите в "by" собственост чрез $map . Това позволява сравнение на единичната стойност с необходимия параметър, "Abe" .

Или дори малко по-модерно, използвайки $expr за MongoDB 3.6 и по-нови:

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

Това би било най-ефективното решение за съпоставяне на последния елемент в масив и всъщност се очаква да замести използването на $where в повечето случаи и особено тук.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Итерация над курсора на Mongodb от агрегат

  2. Разлика между count() и find().count() в MongoDB

  3. Mongoose поддържа ли метода на Mongodb `findAndModify`?

  4. намалява стойността в колекцията до 0

  5. Могат ли $in и $or да се заменят взаимно в MongoDB?