sql >> Databáze >  >> NoSQL >> MongoDB

Jak používat $regex uvnitř $nebo jako agregační výraz

Vše uvnitř $expr je agregační výraz a dokumentace nemusí "tvrdit, že nemůžete explicitně" , ale nedostatek jakéhokoli jmenovaného operátora a JIRA vydání SERVER-11947 určitě to řekni. Takže pokud potřebujete regulární výraz, pak opravdu nemáte jinou možnost než použít $where místo toho:

db.getCollection('permits').find({
  "$where": function() {
    var description = this.inspections
       .sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
       .shift().description;

     return /^Found a .* at the property$/.test(description) ||
           description === "Health Inspection";

  }
})

Stále můžete používat $expr a agregační výrazy pro přesnou shodu, nebo ponechte srovnání v rámci $ kde tak jako tak. V současnosti však MongoDB rozumí pouze regulárním výrazům $regex v rámci výrazu "query" .

Pokud jste skutečně "vyžadují" výraz agregačního kanálu, který vám brání používat $where , pak jediným platným přístupem je nejprve „projektovat“ pole odděleně od pole a poté $match s regulárním dotazovým výrazem:

db.getCollection('permits').aggregate([
  { "$addFields": {
     "lastDescription": {
       "$arrayElemAt": [
         "$inspections.description",
         { "$indexOfArray": [
           "$inspections.inspectionDate",
           { "$max": "$inspections.inspectionDate" }
         ]}
       ]
     }
  }},
  { "$match": {
    "lastDescription": {
      "$in": [/^Found a .* at the property$/,/Health Inspection/]
    }
  }}
])

Což nás vede k tomu, že se zdá, že hledáte položku v poli s maximální hodnotou data. Syntaxe JavaScriptu by měla objasňovat, že správný přístup je místo toho $sort pole na "aktualizaci". Tímto způsobem může být „první“ položka v poli „nejnovější“. A to je něco, co můžete udělat s běžným dotazem.

Chcete-li zachovat objednávku, zajistěte přidání nových položek do pole pomocí $push a $sort takhle:

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  {
    "$push": {
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Ve skutečnosti s prázdným argumentem pole pro $each updateMany() aktualizuje všechny vaše stávající dokumenty:

db.getCollection('permits').updateMany(
  { },
  {
    "$push": {
      "inspections": {
        "$each": [],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

Ty by měly být skutečně nutné pouze tehdy, když ve skutečnosti „změníte“ datum uložené během aktualizací, a tyto aktualizace se nejlépe vydávají pomocí bulkWrite() efektivně provést „jak“ aktualizaci, tak „třídění“ pole:

db.getCollection('permits').bulkWrite([
  { "updateOne": {
    "filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
    "update": {
      "$set": { "inspections.$.inspectionDate": new Date() }
    }
  }},
  { "updateOne": {
    "filter": { "_id": _idOfDocument },
    "update": {
      "$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
    }
  }}
])

Pokud jste však datum ve skutečnosti nikdy „nezměnili“, pak je pravděpodobně smysluplnější jednoduše použít $position modifikátor a "pre-pend" k poli namísto "připojování" a vyhýbání se jakékoli režii $sort :

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  { 
    "$push": { 
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$position": 0
      }
    }
  }
)

S polem trvale seřazeným nebo alespoň vytvořeným tak, že „nejnovější“ datum je ve skutečnosti vždy „prvním“ záznamem, pak můžete jednoduše použít regulární výraz dotazu:

db.getCollection('permits').find({
  "inspections.0.description": { 
    "$in": [/^Found a .* at the property$/,/Health Inspection/]
  }
})

Ponaučení tedy zní, nesnažte se své logice vnutit vypočítané výrazy tam, kde to opravdu nepotřebujete. Neměl by existovat žádný pádný důvod, proč nemůžete objednat obsah pole jako „uložený“, abyste měli „nejnovější datum první " , a i když jste si mysleli, že pole potřebujete v jakémkoli jiném pořadí, pravděpodobně byste měli zvážit, který případ použití je důležitější.

Po přeuspořádání můžete dokonce do určité míry využívat výhod indexu, pokud jsou regulární výrazy buď ukotveny na začátek řetězce, nebo alespoň něco jiného ve výrazu dotazu přesně odpovídá.

V případě, že máte pocit, že opravdu nemůžete změnit pořadí pole, pak $ kde dotaz je vaší jedinou současnou možností, dokud se problém JIRA nevyřeší. Což je doufejme ve skutečnosti pro vydání 4.1, jak je aktuálně zamýšleno, ale to je více než pravděpodobně 6 měsíců až rok při nejlepším odhadu.




  1. jak nainstalovat mongodb php ovladač na Windows 8 a wamp server?

  2. Proč mi mongodb nedává více než 100 dokumentů?

  3. Jak třídit v mangoose?

  4. Při použití expresního balíčku html-pdf se obrázek nevykresluje z cesty dynamického obrázku