#mongodb
#mongodb
Вопрос:
У меня есть данные в следующем формате:
{
"_id" : ObjectId("5f281caf3494701c38711e96"),
"WidgetId" : "0233261",
"Specs" : [
{
"WidgetType" : "A",
"AmountLow" : NumberLong(0),
"AmountHigh" : NumberLong(0),
},
{
"WidgetType: "A",
"AmountLow" : NumberLong(0),
"AmountHigh" : NumberLong(500),
},
{
"WidgetType" : "A"
"AmountLow" : NumberLong(1),
"AmountHigh" : NumberLong(1000),
}
]
}
Однако данные неверны в том смысле, что у меня не может быть значения "Specs.AmountLow" = 0
и "Specs.AmountHigh" > 0
, они должны быть либо 0/0, либо > 0 /> 0.
Мне не повезло найти документы, которые имеют определенную комбинацию "Specs.AmountLow" = 0
и "Specs.AmountHigh" > 0
. Вот два запроса, которые я безуспешно пытался выполнить:
Попытка 1:
db.widgets.find(
{
"Specs.AmountLow" : NumberLong(0),
"Specs.AmountHigh" : {
"$gt" : NumberLong(0)
}
},
{
"WidgetId" : 1.0,
"Specs.AmountLow" : 1.0,
"Specs.AmountHigh" : 1.0
}
)
Приведенный выше запрос отправляет обратно все результаты, если AmountLow
равно 0 или AmountHigh
больше 0, поэтому в данных примера все значения массива совпадают, даже если нет значения 0 /> 0
Я попробовал это следующим:
db.widgets.find(
{
"$and" : [
{
"Specs.$.AmountLow" : NumberLong(0)
},
{
"Specs.$.AmountHigh" : {
"$gt" : NumberLong(0)
}
}
]
},
{
"WidgetId" : 1.0,
"Specs.AmountLow" : 1.0,
"Specs.AmountHigh" : 1.0
}
);
Однако этот не вернул никаких результатов, даже когда у меня были данные, подтвержденные значением 0 /> 0
Как мне написать запрос, который находит конкретную комбинацию вложенных документов AmountLow = 0
и AmountHigh > 0
и, как следствие, как мне обновить ТОЛЬКО те записи, которые у меня есть AmountLow = 1
?
Ожидаемый результат:
{
"_id" : ObjectId("5f281caf3494701c38711e96"),
"WidgetId" : "0233261",
"Specs" : [
{
"WidgetType: "A",
"AmountLow" : NumberLong(0),
"AmountHigh" : NumberLong(500),
}
]
}
Ответ №1:
Вы можете попробовать,
Когда вы используете $-positional, это вернет только один соответствующий документ из массива и в массиве
- использовать
$elemMatch
для сопоставления элементов массива - используйте
$
позиционное значение после имени поля массива в проекции,
db.widgets.find({
Specs: {
$elemMatch: {
AmountLow: 0,
AmountHigh: {
$gt: 0
}
}
}
},
{
_id: 1,
WidgetId: 1,
"Specs.$": 1
})
Вместо приведенного выше примера вы можете использовать aggregate(), этот пример вернет все соответствующие документы из массива,
- $filter для получения отфильтрованных документов из массива на основе условий
db.widgets.aggregate([
{
$addFields: {
Specs: {
$filter: {
input: "$Specs",
cond: {
$and: [
{ $eq: ["$$this.AmountLow", 0] },
{ $gt: ["$$this.AmountHigh", 0] }
]
}
}
}
}
}
])