Обычно неправильно хранить / сравнивать Date
значения в виде строк.
Вы можете сделать это следующим образом. Сначала преобразуйте строки в соответствующие Date
объекты:
db.collection.updateMany(
{},
[
{
$set: {
inventory: {
$map: {
input: "$inventory",
as: "inventory",
in: {
$mergeObjects: [
"$$inventory",
{
batch: {
$map: {
input: "$$inventory.batch",
in: {
quantity: "$$this.quantity",
manf_date: { $dateFromString: { dateString: "$$this.manf_date", format: "%d-%m-%Y" } },
exp_date: { $dateFromString: { dateString: "$$this.exp_date", format: "%d-%m-%Y" } }
}
}
}
}
]
}
}
}
}
}
]
)
Когда вам нужно работать со значениями Date, тогда я рекомендую библиотеку Moment. js. Запрос будет выглядеть следующим образом:
db.collection.find(
{
"inventory.batch": {
$elemMatch: {
exp_date: {
$eq: moment().utc().add(30, 'days').startOf('day').toDate()
}
}
}
}
)
или в виде агрегации:
db.collection.aggregate([
{
$match: {
"inventory.batch": {
$elemMatch: {
exp_date: {
$eq: moment().utc().add(30, 'days').startOf('day').toDate()
}
}
}
}
}
])
Обратите внимание, по умолчанию $dateFromString
использует UT C раз, тогда как moment()
по умолчанию использует ваше местное время. Таким образом, вы должны использовать либо moment().utc()
, либо указать поле timezone
в $dateFromString
.
. Если вы настаиваете на сохранении строковых значений в качестве даты, вы также можете использовать
db.collection.find(
{
"inventory.batch": {
$elemMatch: {
exp_date: {
$eq: moment().add(30, 'days').startOf('day').format("DD-MM-YYYY")
}
}
}
}
)
Однако это не удастся, если вы запросите с $gte, $ge, $lt, $lte
операторами.
Обновите
Если у вас нет доступа к moments
, вы можете запустить в чисто в агрегации:
db.collection.aggregate([
{ $unwind: "$inventory" },
{ $set: { ts: { $dateToParts: { date: { $add: ["$$NOW", { $multiply: [1000, 60, 60, 24, 30] }] } } } } },
{
$set: {
ts: {
$dateFromParts: {
year: "$ts.year",
month: "$ts.month",
day: "$ts.day",
timezone: "UTC"
}
}
}
},
{ $set: { matches: { $in: ["$ts", "$inventory.batch.exp_date"] } } },
{
$group: {
_id: { _id: "$_id", branch_id: "$branch_id" },
inventory: { $push: "$$ROOT.inventory" },
matches: { $push: "$$ROOT.matches" }
}
},
{ $match: { $expr: { $anyElementTrue: "$matches" } } },
{ $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$_id"] } } },
{$unset: "matches"}
])
или, если вы хотите написать все в одной агрегации:
db.collection.aggregate([
{ $unwind: "$inventory" },
{
$set: {
"inventory.batch": {
$map: {
input: "$inventory.batch",
in: {
quantity: "$$this.quantity",
manf_date: { $dateFromString: { dateString: "$$this.manf_date", format: "%d-%m-%Y" } },
exp_date: { $dateFromString: { dateString: "$$this.exp_date", format: "%d-%m-%Y" } }
}
}
}
}
},
{ $set: { ts: { $dateToParts: { date: { $add: ["$$NOW", { $multiply: [1000, 60, 60, 24, 30] }] } } } } },
{
$set: {
ts: {
$dateFromParts: {
year: "$ts.year",
month: "$ts.month",
day: "$ts.day",
timezone: "UTC"
}
}
}
},
{ $set: { matches: { $in: ["$ts", "$inventory.batch.exp_date"] } } },
{
$group: {
_id: { _id: "$_id", branch_id: "$branch_id" },
inventory: { $push: "$$ROOT.inventory" },
matches: { $push: "$$ROOT.matches" }
}
},
{ $match: { $expr: { $anyElementTrue: "$matches" } } },
{ $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$_id"] } } },
{ $unset: "matches" }
])