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

Намиране на два елемента в масив от документи, които се появяват в даден ред

Ако искате такъв вид ограничение в заявката, тогава имате основно две опции в зависимост от това какво поддържа вашата MongoDB версия:

MongoDB 3.6

За предпочитане е да използвате $expr "в допълнение" към всякакви нормални условия на заявка, за да изберете действително валидни документи:

var A = 10, B = 40;

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$expr": {
    "$lt": [
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$indexOfArray": [ "$subDocs.value", A ]}
      ]},
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$indexOfArray": [ "$subDocs.value", B ]}  
      ]}
    ]
  }
})

Или съвпадение на "последния" събитие:

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$expr": {
    "$lt": [
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$subtract": [
          { "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
          { "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, A ] }
        ]}
      ]},
      { "$arrayElemAt": [
        "$subDocs.index",
        { "$subtract": [
          { "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
          { "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, B ] }
        ]}
      ]}
    ]
  }
})

По-ранни версии

Същото нещо, но без собствени оператори, трябва да използвате оценката на JavaScript на $където :

var A = 10, B = 40;

Model.find({
  "subDocs.value": { "$all": [A, B] },
  "$where": `this.subDocs.find( e => e.value === ${A}).index
      < this.subDocs.find( e => e.value === ${B}).index`
})

Или съвпадение на "последния" събитие:

Model.find({
  "subDocs.value": { "$all": [10,40] },
  "$where": `let arr = this.subDocs.reverse();
      return arr.find( e => e.value === ${A}).index
        > arr.find( e => e.value === ${B}).index`
})

Ако имате нужда от това в конвейер за агрегиране, тогава ще използвате $редактиране и вместо това подобна логика на първия пример:

var A = 10, B = 40;

Model.aggregate([
  { "$match": { "subDocs.value": { "$all": [A, B] } } },
  { "$redact": {
    "$cond": {
      "if": {
        "$lt": [
          { "$arrayElemAt": [
            "$subDocs.index",
            { "$indexOfArray": [ "$subDocs.value", A ]}
          ]},
          { "$arrayElemAt": [
            "$subDocs.index",
            { "$indexOfArray": [ "$subDocs.value", B ]}  
          ]}
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Достатъчно е да се каже, че „логиката на сравнението“ всъщност не е естествена за самите „изрази на оператор на заявка“, така че единствената част, която „оптимално“ може да се приложи към индекс, използвайки $all оператор на заявка във всички случаи. Основната оставаща логика всъщност се прилага „след“ този основен израз е оценен и „в допълнение към“, за да не се връщат резултати, освен тези, които отговарят на израза с $expr или $where .

Основната логика на всеки е по същество да извлече стойността на "index" свойство от "първия" член на масива, което действително съответства на съответната стойност в "value" Имот. Когато това е „по-малко от“, тогава условието е true и това удовлетворява документа, който се връща.

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

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

Вижте също документацията за $arrayElemAt , $indexOfArray , $lt и Array.find() за JavaScript




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Преведете FilterDefinition<TDocument> към обикновена json mongo заявка, която мога да изпълнявам в mongo shell

  2. Не мога да инсталирам mongodb doctrine в symfony2 с composer

  3. Как да използвам променлива mongoose заявка?

  4. Как да премахнете всички елементи от колекция MongoDB

  5. Модулът не е намерен:Грешка:Не може да се разреши „dns“ при използване на MongoDB