Все внутри $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
ивыражения агрегации для точного соответствия или просто сохраняйте сравнение в пределах $where
в любом случае.Но в настоящее время единственное регулярное выражение, которое понимает MongoDB, это $regex
внутри выражения "query" .
Если вы действительно "require" выражение конвейерного агрегации, которое не позволяет использовать $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
}
}
}
)
С массивом, постоянно отсортированным или по крайней мере построенным так«последняя» дата на самом деле всегда является «первой» записью, тогда вы можете просто использовать обычный запрос expression:
db.getCollection('permits').find({
"inspections.0.description": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
})
Итак, урок здесь - не пытайтесь навязывать вычисленные выражения вашей логике там, где вам действительно не нужно.Не должно быть веских причин, по которым вы не можете заказать содержимое массива как «сохраненное», чтобы иметь "самую последнюю дату first " , и даже если вы думали, что вам нужен массив в любом другомВ таком случае вам, вероятно, следует взвесить, какой вариант использования более важен.
После повторного вывода вы даже можете в некоторой степени воспользоваться индексом, если регулярные выражения привязаны к началу строки или, по крайней мере,что-то еще в выражении запроса делает точное совпадение.
Если вы чувствуете, что действительно не можете переупорядочить массив, тогда запрос $where
- ваш единственный вариант до появления проблемы JIRA.решает.К счастью, это действительно актуальная версия 4.1, но в лучшем случае это, скорее всего, от 6 месяцев до года.