MongoDB магазин и запрос ценовой истории - PullRequest
2 голосов
/ 27 апреля 2019

Я работаю с набором данных, который является каталогом продукции. Там всего около 20к предметов, и изменение цены происходит редко. Может быть, 100 обновлений в месяц, максимум.

Однако в этом случае интересным является изменение цены, и я хочу отслеживать цены в течение длительных периодов времени.

Я пытаюсь найти лучший способ хранения ценовых данных таким образом, чтобы упростить запрос.

В настоящее время он хранится в массиве в документе продукта. Просто цена вместе с отметкой времени. Учитывая небольшой и довольно статичный набор данных, как бы вы разработали модель?

Кроме того, бонусный вопрос, как бы выглядел фильтр, который мог бы дать список продуктов, где текущая цена ниже предыдущей?

Пример данных, упрощенная версия модели:

// Match, current price is lower than previous price

db.TestC.insert({Name: "P1", CurrentPrice: 10.0,  PriceHistory: [{Price: 14.0, Timestamp: ISODate("2019-04-26T07:11:11.939Z")}, {Price: 12.0, Timestamp: ISODate("2019-04-27T07:11:11.939Z")}]})

// No match, price history doesn't exist yet

db.TestC.insert({Name: "P2", CurrentPrice: 10.0, PriceHistory: null})

// No match, previous price was lower than current price

db.TestC.insert({Name: "P3", CurrentPrice: 18.0, PriceHistory: [{Price: 14.0, Timestamp: ISODate("2019-04-26T07:11:11.939Z")}, {Price: 12.0, Timestamp: ISODate("2019-04-27T07:11:11.939Z")}]})

Отредактируйте после дополнительной работы над этим:

Итак, я наконец-то придумал именно то, что мне было нужно, и подумал, что должен поделиться, если кому-то это поможет:

db.TestCollection.aggregate({
    '$project': {
      'Number': 1, 
      'AssortmentKey': 1, 
      'AssortmentName': 1, 
      'NameExtension': 1, 
      'Name': 1, 
      'CurrentPrice': {
        '$arrayElemAt': [
          '$PriceHistory', -1
        ]
      }, 
      'PreviousPrice': {
        '$arrayElemAt': [
          '$PriceHistory', -2
        ]
      }
    }
  }, {
    '$match': {
      '$expr': {
        '$lt': [
          '$CurrentPrice.Price', '$PreviousPrice.Price'
        ]
      }
    }
  })

1 Ответ

2 голосов
/ 27 апреля 2019

Я бы организовал документы точно так же. Просто имейте в виду, что MongoDB имеет жесткий лимит в 16 МБ на документ, что является очень очень высоким пределом, почти недоступным в таком случае, но все же оно существует.

Если вам нужно знать только текущую цену без истории, вы можете делать запросы, используя проекцию, чтобы избежать отправки этого огромного массива по сети:

db.TestC.find({Name: 'P1'}, {Name, CurrentPrice}});

Что касается бонусного вопроса, вы можете использовать структуру агрегирования:

db.TestC.aggregate([
  {
    $project: {
      Name: 1,
      CurrentPrice: 1,
      PreviousPrice: { // remove this key if you don't need to have previous price in the result
        $arrayElemAt: [
          "$PriceHistory",
          0 // depends on whether you store prices by pushing to the end of history array, or to the beginning of it
        ]
      },
      IsCurrentPriceLower: {
        $lt: [
          "$CurrentPrice",
          {
            $arrayElemAt: [
              "$PriceHistory",
              0 // depends on whether you store prices by pushing to the end of history array, or to the beginning of it
            ]
          }
        ]
      }
    },
  },
  {
    $match: {
      IsCurrentPriceLower: true
    }
  }
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...