根据嵌入式对象数组上元素之间的最大差异进行查找

时间:2018-09-13 13:16:59

标签: mongodb mongodb-query

给出如下产品列表:

{
    "_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 :(得分:1)

假设

  1. 您想要给定国家与任何其他国家
  2. 之间的最大差异
  3. 没有重复的产品ID (如果有,则使用最新产品,这要归功于"$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"
      }
    ]
  }
]

答案 1 :(得分:0)

谢谢@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()