我有一个文档集合,我想在这些文档中找到data
对象中每个可能的字段对的每个比率的最大值。例如:
文档:
[
{ data: { a: 1, b: 5, c: 2 } },
{ data: { a: 4, b: 1, c: 1 } },
{ data: { a: 2, b: 4, c: 3 } }
]
所需的输出:
{
a: { a: 1, b: 4, c: 4 },
b: { a: 5, b: 1, c: 2.5 },
c: { a: 2, b: 1, c: 1 }
}
因此,输出a.b
是a:b比率1/5
,4/1
和2/4
中最大的比率。
所以我想我首先使用$objectToArray
来转换data
,然后对结果进行$unwind
转换,但是我很难弄清楚如何将所有内容组合在一起。我所拥有的文档数量不会太大,但是data
中的键数量可以低至数千,因此我不确定Mongo能够处理多堆{ {1}},并比较类似的值。
答案 0 :(得分:1)
您可以尝试以下聚合:
db.col.aggregate([
{
$addFields: { data: { $objectToArray: "$data" } }
},
{
$project: {
pairs: {
$map: {
input: { $range: [ 0, { $multiply: [ { $size: "$data" }, { $size: "$data" } ] } ] },
as: "index",
in: {
$let: {
vars: {
leftIndex: { $floor: { $divide: [ "$$index", { $size: "$data" } ] } },
rightIndex: { $mod: [ "$$index", { $size: "$data" } ] }
},
in: {
l: { $arrayElemAt: [ "$data", "$$leftIndex" ] },
r: { $arrayElemAt: [ "$data", "$$rightIndex" ] }
}
}
}
}
}
}
},
{ $unwind: "$pairs" },
{
$group: {
_id: { l: "$pairs.l.k", r: "$pairs.r.k" },
value: { $max: { $divide: [ "$pairs.l.v", "$pairs.r.v" ] } }
}
},
{
$sort: {
"_id.l": 1, "_id.r": 1
}
},
{
$group: {
_id: "$_id.l",
values: { $push: { k: "$_id.r", v: "$value" } }
}
},
{
$addFields: { values: { $arrayToObject: "$values" } }
},
{
$project: {
root: [ { k: "$_id", v: "$values" } ]
}
},
{
$sort: { "root.k": 1 }
},
{
$replaceRoot: {
newRoot: {
$arrayToObject: "$root"
}
}
}
])
基本上,您需要$objectToArray和$arrayToObject在数组和对象之间进行转换。基本上,关键是要为每个对象生成nxn
对(在这种情况下为3x3=9
)。您可以使用$range运算符执行此类迭代。然后将$mod和$divide与$floor一起使用,您可以获得类似(0,0)...(2,2)
的索引对。然后,您只需要$group和$max来获取每种货币对类型的最大值(例如a
和b
等)。要获得最终形状,您还需要$replaceRoot。
输出:
{ "a" : { "a" : 1, "b" : 4, "c" : 4 } }
{ "b" : { "a" : 5, "b" : 1, "c" : 2.5 } }
{ "c" : { "a" : 2, "b" : 1, "c" : 1 } }