Todo dentro de $expr
es una expresión de agregación, y es posible que la documentación no "diga que no puede explícitamente" , pero la falta de cualquier operador con nombre
y el problema de JIRA SERVER-11947
ciertamente decir eso. Entonces, si necesita una expresión regular, realmente no tiene otra opción que usar $where
en cambio:
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";
}
})
Todavía puede usar $expr
y expresiones de agregación para una coincidencia exacta, o simplemente mantenga la comparación dentro de $where
de todos modos. Pero en este momento, las únicas expresiones regulares que entiende MongoDB son $regex
dentro de una expresión "query"
.
Si realmente "require" una expresión de canalización de agregación que le impide usar $where
, entonces el único enfoque válido actual es primero "proyectar" el campo por separado de la matriz y luego $match
con la expresión de consulta regular:
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/]
}
}}
])
Lo que nos lleva al hecho de que parece estar buscando el elemento en la matriz con el valor de fecha máximo. La sintaxis de JavaScript debería dejar en claro que el enfoque correcto aquí es $sort
la matriz en "actualizar". De esa forma, el "primer" elemento de la matriz puede ser el "más reciente". Y esto es algo que puede hacer con una consulta regular.
Para mantener el orden, asegúrese de agregar nuevos elementos a la matriz con $push
y $sort
así:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$sort": { "inspectionDate": -1 }
}
}
}
)
De hecho, con un argumento de matriz vacío para $each
an updateMany()
actualizará todos sus documentos existentes:
db.getCollection('permits').updateMany(
{ },
{
"$push": {
"inspections": {
"$each": [],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Estos realmente solo deberían ser necesarios cuando, de hecho, "altera" la fecha almacenada durante las actualizaciones, y esas actualizaciones se emiten mejor con bulkWrite()
para hacer efectivamente "tanto" la actualización como la "clasificación" de la matriz:
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 } } }
}
}}
])
Sin embargo, si nunca "alteró" la fecha, probablemente tenga más sentido simplemente usar $position
modificador y "pre-pend" a la matriz en lugar de "agregar", y evitando cualquier sobrecarga de un $sort
:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$position": 0
}
}
}
)
Con la matriz ordenada permanentemente o al menos construida para que la fecha "más reciente" sea siempre la "primera" entrada, entonces simplemente puede usar una expresión de consulta regular:
db.getCollection('permits').find({
"inspections.0.description": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
})
Entonces, la lección aquí es que no intentes forzar expresiones calculadas en tu lógica donde realmente no las necesitas. No debería haber ninguna razón convincente por la que no pueda ordenar el contenido de la matriz como "almacenado" para tener la "última fecha primera " , e incluso si pensó que necesitaba la matriz en cualquier otro orden, entonces probablemente debería sopesar qué caso de uso es más importante.
Una vez reordenado, incluso puede aprovechar un índice hasta cierto punto, siempre que las expresiones regulares estén ancladas al comienzo de la cadena o al menos algo más en la expresión de consulta haga una coincidencia exacta.
En el caso de que sienta que realmente no puede reordenar la matriz, entonces el $where
query es su única opción presente hasta que se resuelva el problema de JIRA. Lo que, con suerte, es para la versión 4.1 según el objetivo actual, pero es más que probable que sea de 6 meses a un año en el mejor cálculo.