Невозможно использовать позиционный оператор

#mongodb #mongoose

#mongodb #mongoose

Вопрос:

Возникли проблемы с использованием $[<identifier>] оператора в mongodb / mongoose при использовании $set во вложенном массиве. Кажется, у меня это не работает при использовании item.nModified всегда равно 0, и в базе данных ничего не обновляется. Есть идеи, что я делаю не так?

 await Product.update(
          {productName: product.productName},
          { "$set": {
              "stores.$[index].trackingUrl": 'url',
            } },
          { "arrayFilters": [
              { "index": 0 },
            ] },

        ).then((item) => {
          console.log("Updated", item.nModified); 
        });
  

Если я удалю объект arrayFilters и использую "stores.$[].trackingUrl": 'url' , без оператора он правильно обновит значение.

Если я использую "stores.$[].trackingUrl": 'url' и оставляю arrayFilters, я получаю эту ошибку

 MongoError: The array filter for identifier 'index' was not used in the update { $set: { stores.$[].trackingUrl: "url" } }
  

Если я изменю 0 на 1 в {"index": 0} , появится эта ошибка. На данный момент у меня есть только 1 объект в массиве stores, поэтому неудивительно, что здесь происходит сбой.

  CastError: Cast to embedded failed for value "1" at path "stores"
  

Схема для Product

 const ProductSchema = new Schema({
  ean: String,
  productName: String,
  mainCategory: String,
  subCategory: String,
  group: String,
  subSubCategory: String,
  lowestPrice: Number,
  isPopular: Boolean,
  description: String,
  keyword: String,

  stores: [
    {
      name: String,
      programId: Number,
      productPrice: Number,
      productUrl: String,
      imageUrl: String,
      sku: String,
      currency: String,
      manufacturerArticleNumber: String,
      manufacturer: String,
      oldPrice: Number,
      shipping: Number,
      inStock: Boolean,
      market: String,
      approvalStatus: Number,
      trackingUrl: String,
      productDescription: String,
      timestamp: String,
    },
  ],
});
  

Один документ

 { _id: 5f3bf084fa56743527344454,
  ean: '000',
  productName: 'name',
  lowestPrice: 5,
  mainCategory: 'Leksaker',
  group: 'Leksaker',
  subCategory: 'Djur',
  subSubCategory: '',
  stores:
   [ { _id: 5f3cc819d28fc65d915016bc,
       name: 'Stor amp; Liten',
       programId: 0,
       productPrice: 359,
       productUrl: 'https://www.storochliten.se/papo-kaprosuchus',
       imageUrl:
        'https://media.storochliten.se/product-images/XL//papo-kaprosuchus-0.jpg',
       sku: '317969',
       currency: 'SEK',
       manufacturerArticleNumber: 'P55056',
       manufacturer: 'Papo',
       oldPrice: 359,
       shipping: 0,
       inStock: true,
       market: 'SE',
       trackingUrl: '', //expect to insert "url" here
       productDescription:'text',
       timestamp: '2020-08-19T06:35:05.595Z' } ],

}
  

Комментарии:

1. Можете ли вы показать документ, который пытаетесь изменить (или только его часть и ожидаемый результат?

2. да, есть обновление!

Ответ №1:

Часть идентификатора отфильтрованного позиционного оператора используется для указания условия на основе поля вложенного документа. Ваш пример не работает, потому что нет поля индекса для хранилища.

Если вы хотите обновить первый элемент, вы можете просто использовать точечную нотацию:

 { $set: { 'stores.0.trackingUrl': 'url' }
  

Если вам нужно идентифицировать себя store по какому-либо полю, вы можете попробовать с _id (или любым другим существующим полем):

 await Product.update(
        {productName: product.productName},
        { "$set": {
            "stores.$[store].trackingUrl": 'url',
            } },
        { "arrayFilters": [
            { "store._id": 5f3cc819d28fc65d915016bc },
            ] },

        ).then((item) => {
        console.log("Updated", item.nModified); 
        });
  

Комментарии:

1. А, окей, спасибо! Потребовалось некоторое время, чтобы понять, так как я был немного сбит с толку store переменной. Я думал, что переменная определена в arrayFilter , а не наоборот.