Есть ли способ сопоставить 2 конкретных значения полей в массиве вложенных документов в mongodb?

#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] }
            ]
          }
        }
      }
    }
  }
])
  

Игровая площадка