Всичко вътре $expr
е израз за агрегиране и документацията може да не "казва, че не можете изрично" , но липса на който и да е наименуван оператор
и проблемът на JIRA SERVER-11947
със сигурност го кажи. Така че, ако имате нужда от регулярен израз, тогава наистина нямате друга опция освен да използвате $where
вместо това:
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";
}
})
Все още можете да използвате $expr
и изрази за агрегиране за точно съвпадение или просто запазете сравнението в $където
така или иначе. Но в момента единствените регулярни изрази, които MongoDB разбира, са $regex
в рамките на израз "query"
.
Ако наистина сте „изисквали“ израз на тръбопровода за агрегиране, който ви пречи да използвате $whereкод>
, тогава единственият настоящ валиден подход е първо да се „проектира“ полето отделно от масива и след това $match
с регулярния израз за заявка:
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/]
}
}}
])
Което ни води до факта, че изглежда търсите елемента в масива с максималната стойност на датата. Синтаксисът на JavaScript трябва да изяснява, че правилният подход тук е вместо $sort
масива на "актуализация". По този начин "първият" елемент в масива може да бъде "последният". И това е нещо, което можете да направите с обикновена заявка.
За да поддържате реда, уверете се, че нови елементи са добавени към масива с $push
и $sort
като това:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Всъщност с празен аргумент за масив към $each
updateMany()
ще актуализира всички ваши съществуващи документи:
db.getCollection('permits').updateMany(
{ },
{
"$push": {
"inspections": {
"$each": [],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Те наистина трябва да са необходими само когато всъщност „промените“ датата, съхранена по време на актуализации, и тези актуализации се издават най-добре с bulkWrite()
за ефективно извършване на "и двете" актуализацията и "сортирането" на масива:
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 } } }
}
}}
])
Ако обаче никога не сте „променяли“ датата, вероятно ще има по-голям смисъл просто да използвате $position
модификатор и „предварително добавяне“ към масива вместо „добавяне“ и избягване на всякакви допълнителни разходи на $sort
:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$position": 0
}
}
}
)
Когато масивът е постоянно сортиран или поне конструиран така, че „последната“ дата всъщност винаги е „първият“ запис, тогава можете просто да използвате израз за редовна заявка:
db.getCollection('permits').find({
"inspections.0.description": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
})
Така че урокът тук е да не се опитвате да наложите изчислени изрази върху логиката си, когато наистина не е необходимо. Не трябва да има убедителна причина, поради която не можете да наредите съдържанието на масива като "съхранено", за да има "най-нова дата първа " и дори ако смятате, че имате нужда от масива в друг ред, тогава вероятно трябва да прецените кой случай на използване е по-важен.
Веднъж пренаредени, можете дори да се възползвате от индекс до известна степен, стига регулярните изрази да са или закотвени към началото на низа, или поне нещо друго в израза на заявката има точно съвпадение.
В случай, че смятате, че наистина не можете да пренаредите масива, тогава $където
query е единствената ви настояща опция, докато проблемът с JIRA не бъде разрешен. Което се надяваме всъщност да е за изданието 4.1, както е предвидено в момента, но това е повече от вероятно 6 месеца до една година при най-добра оценка.