Alt inde i $expr
er et aggregeringsudtryk, og dokumentationen må ikke "sige du ikke eksplicit" , men manglen på en navngiven operatør
og JIRA-udgaven SERVER-11947
bestemt sige det. Så hvis du har brug for et regulært udtryk, har du virkelig ingen anden mulighed end at bruge $where
i stedet:
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";
}
})
Du kan stadig bruge $expr
og aggregeringsudtryk for et nøjagtigt match, eller bare behold sammenligningen inden for $hvor
alligevel. Men på nuværende tidspunkt er de eneste regulære udtryk, MongoDB forstår, $regex
inden for et "query"-udtryk
.
Hvis du faktisk "krævede" et aggregeringspipeline-udtryk, der udelukker dig fra at bruge $where
, så er den eneste aktuelle gyldige tilgang først at "projektere" feltet separat fra arrayet og derefter $match
med det regulære forespørgselsudtryk:
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/]
}
}}
])
Hvilket leder os til det faktum, at du ser ud til at lede efter varen i arrayet med den maksimale datoværdi. JavaScript-syntaksen burde gøre det klart, at den korrekte tilgang her i stedet er at $sort
arrayet på "opdatering". På den måde kan det "første" element i arrayet være det "seneste". Og det er noget, du kan gøre med en almindelig forespørgsel.
For at opretholde rækkefølgen skal du sikre dig, at nye elementer tilføjes til arrayet med $push
og $sort
sådan her:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Faktisk med et tomt array-argument til $each
en updateMany()
vil opdatere alle dine eksisterende dokumenter:
db.getCollection('permits').updateMany(
{ },
{
"$push": {
"inspections": {
"$each": [],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Disse burde egentlig kun være nødvendige, når du faktisk "ændrer" den dato, der er gemt under opdateringer, og disse opdateringer udstedes bedst med bulkWrite()
for effektivt at udføre "både" opdateringen og "sorten" af arrayet:
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 } } }
}
}}
])
Men hvis du aldrig faktisk "ændrede" datoen, så giver det sandsynligvis mere mening blot at bruge $position
modifikator og "pre-pend" til arrayet i stedet for "appending" og undgå enhver overhead af en $sort
:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$position": 0
}
}
}
)
Med arrayet permanent sorteret eller i det mindste konstrueret, så den "seneste" dato faktisk altid er den "første" post, så kan du blot bruge et regulært forespørgselsudtryk:
db.getCollection('permits').find({
"inspections.0.description": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
})
Så lektionen her er, prøv ikke at tvinge beregnede udtryk på din logik, hvor du virkelig ikke behøver det. Der burde ikke være nogen tvingende grund til, at du ikke kan bestille matrixindholdet som "gemt" til at have den "seneste dato første " , og selvom du troede, at du havde brug for arrayet i en hvilken som helst anden rækkefølge, bør du sandsynligvis afveje, hvilken brugssag der er vigtigst.
Når du først er blevet reoderet, kan du endda drage fordel af et indeks til en vis grad, så længe de regulære udtryk enten er forankret til begyndelsen af strengen eller i det mindste noget andet i forespørgselsudtrykket matcher nøjagtigt.
Hvis du føler, at du virkelig ikke kan omarrangere arrayet, så