Найти наибольшую разницу между элементами в массиве встроенных объектов - PullRequest
0 голосов
/ 13 сентября 2018

Дан список продуктов, подобных этому:

{
    "_id" : ObjectId("5a594f8eff9da13c9d415a63"),
    "productId" : "xxx",
    "date" : "2018-09-13",
    "prices" : [
        {
            "country" : "en",
            "price" : 16.5,
            "currency" : "EUR"
        },
        {
            "country" : "es",
            "price" : 17.78,
            "currency" : "EUR"
        },
        {
            "country" : "fr",
            "price" : 18.08,
            "currency" : "EUR"
        },
        {
            "country" : "de",
            "price" : 18.89,
            "currency" : "EUR"
        },
        {
            "country" : "it",
            "price" : 27.49,
            "currency" : "EUR"
        }
    ]
}

Учитывая код страны и дату, есть ли способ найти товары для этой даты и заказа по разнице между ценой для страны?

Заранее большое спасибо

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Спасибо @ jaksz,

Наконец, я использую этот подход, который работает как шарм (потому что меньшая цена всегда находится в первой позиции массива):

db.productPrices.aggregate(
                     [
  {
    "$match": {
    "date": "2018-09-13" // replace with date variable
    }
  },
  {
      "$group": {
      "_id": "$productId",
      "prices": {
          "$last": "$prices"
      }
    }
  },
  {
      "$addFields": {
      "pricesObj": {
          "$map": {
              "input": "$prices",
          "in": {
                  "k": "$$this.country",
            "v": "$$this.price"
          }
        }
      }
    }
  },
  {
      "$addFields": {
      "pricesObj": {
          "$arrayToObject": "$pricesObj"
      }
    }
  },
  {
      "$addFields": {
      "reference": "$pricesObj.es" // replace with country variable
    }
  },
  {
      "$addFields": {
      "cheapest": {
          "$arrayElemAt": ["$prices", 0]
      }
    }
  },
  {
      "$addFields": {
      "difference": {
          "$abs": {
              "$subtract": ["$reference", "$cheapest.price"]

        }
      }
    }
  },
  {
      "$project": {
      "_id": 1,
      "prices": "$prices",
      "difference": "$difference"
    }
  },
  {
      "$sort": {
      "difference": -1
    }
  }
]).pretty()
0 голосов
/ 14 сентября 2018

Предполагая, что

  1. вы хотите самую большую разницу между данной страной и любой другой страной и
  2. , существует дублирующих идентификаторов продуктов (если есть, последний продукт будет использоваться, благодаря этой строке "$last": "$prices"),

попробуйте это:

db.collection.aggregate([
  {
    "$match": {
      "date": "2018-09-13" // replace with date variable
    }
  },
  {
    "$group": {
      "_id": "$productId",
      "prices": {
        "$last": "$prices"
      }
    }
  },
  {
    "$addFields": {
      "pricesObj": {
        "$map": {
          "input": "$prices",
          "in": {
            "k": "$$this.country",
            "v": "$$this.price"
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "pricesObj": {
        "$arrayToObject": "$pricesObj"
      }
    }
  },
  {
    "$addFields": {
      "reference": "$pricesObj.es" // replace with country variable
    }
  },
  {
    "$addFields": {
      "differences": {
        "$map": {
          "input": "$prices",
          "in": {
            "country": "$$this.country",
            "difference": {
              "$abs": {
                "$subtract": [
                  "$$this.price",
                  "$reference"
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "biggestDifference": {
        "$reduce": {
          "input": "$differences",
          "initialValue": {
            difference: 0
          },
          "in": {
            "$cond": [
              {
                "$gt": [
                  "$$this.difference",
                  "$$value.difference"
                ]
              },
              "$$this",
              "$$value"
            ]
          }
        }
      }
    }
  },
  {
    "$project": {
      "_id": 1,
      "biggestDifference": "$biggestDifference.difference"
    }
  },
  {
    "$sort": {
      "biggestDifference": -1
    }
  }
])

Я уверен, что это можетбыть выражено более кратко, но это работает: https://mongoplayground.net/p/y67jhhFBB9l

Выход выглядит так:

[
  {
    "_id": "xxy",
    "biggestDifference": 12295.109999999999
  },
  {
    "_id": "xxx",
    "biggestDifference": 98.72
  }
]

для этого ввода:

[
  {
    "productId": "xxx",
    "date": "2018-09-13",
    "prices": [
      {
        "country": "en",
        "price": 116.5,
        "currency": "EUR"
      },
      {
        "country": "es",
        "price": 17.78,
        "currency": "EUR"
      },
      {
        "country": "fr",
        "price": 18.08,
        "currency": "EUR"
      },
      {
        "country": "de",
        "price": 18.89,
        "currency": "EUR"
      },
      {
        "country": "it",
        "price": 27.49,
        "currency": "EUR"
      }
    ]
  },
  {
    "productId": "xxy",
    "date": "2018-09-13",
    "prices": [
      {
        "country": "en",
        "price": 16.5,
        "currency": "EUR"
      },
      {
        "country": "es",
        "price": 17.78,
        "currency": "EUR"
      },
      {
        "country": "fr",
        "price": 18.08,
        "currency": "EUR"
      },
      {
        "country": "de",
        "price": 12312.89,
        "currency": "EUR"
      },
      {
        "country": "it",
        "price": 997.49,
        "currency": "EUR"
      }
    ]
  }
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...