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.