产品和变种价格
查找尺寸较小的所有products.Variants.Price
的最小值并将其更新15%
{
"_id" : 23,
"name" : "Polo Shirt",
"Variants" : [
{
"size" : "Large",
"Price" : 82.42
},
{
"size" : "Medium",
"Price" : 20.82 // this should get increased by 15%
},
{
"size" : "Small",
"Price" : 42.29
}
]
},
{
"_id" : 24,
"name" : "Polo Shirt 2",
"Variants" : [
{
"size" : "Large",
"Price" : 182.42
},
{
"size" : "Medium",
"Price" : 120.82 // this should get increased by 15%
},
{
"size" : "Small",
"Price" : 142.29
}
]
}
我开始这样的事情。不确定这是否是正确的开始
db.products.find().forEach(function(product){
var myArr = product.Variants;
print(myArr.min());
});
答案 0 :(得分:0)
这里存在一个问题,你不能在一个更新语句中识别"最小值"数组中的值与位置更新一起使用,因此您对当前方法的方法是正确的。
可以说,更好的方法是预先确定哪个元素是最小元素,然后将其传递给更新。您可以使用.aggregate()
:
var result = db.products.aggregate([
{ "$unwind": "$Variants" },
{ "$sort": { "_id": 1, "Variants.price" } }
{ "$group": {
"_id": "$_id",
"size": { "$first": "$Variants.size" },
"price": { "$first": "$Variants.price" }
}},
{ "$project": {
"size": 1,
"price": 1,
"adjusted": { "$multiply": [ "$price", 1.15 ] }
}}
])
当然,这只是每个产品的最低Variant项目详细信息的结果,但您可以使用这样的结果:
result.result.forEach(function(doc) {
db.products.update(
{
"_id": doc._id,
"Variants": { "$elemMatch": {
"size": doc.size,
"price": doc.price
}}
},
{
"$set": {
"Variants.$.price": doc.adjusted
}
}
}
})
这不是最好的形式,但它至少可以通过迭代数组来消除一些开销,并允许在服务器硬件上进行计算,这可能是客户端的更高规格。
直到你为MongoDB 2.6及更高版本提供一些可用的功能,它仍然看起来并不太多。值得注意的是,聚合获得了响应的光标,您现在也可以执行"bulk updates"。所以表格可以像这样改变:
var cursor = db.products.aggregate([
{ "$unwind": "$Variants" },
{ "$sort": { "_id": 1, "Variants.price" } }
{ "$group": {
"_id": "$_id",
"size": { "$first": "$Variants.size" },
"price": { "$first": "$Variants.price" }
}},
{ "$project": {
"size": 1,
"price": 1,
"adjusted": { "$multiply": [ "$price", 1.15 ] }
}}
]);
var batch = [];
while ( var doc = cursor.next() ) {
batch.push({
"q": {
"_id": doc._id,
"Variants": { "$elemMatch": {
"size": doc.size,
"price": doc.price
}}
},
"u": {
"$set": {
"Variants.$.price": doc.adjusted
}
}
});
if ( batch.length % 500 == 0 ) {
db.command({ "update": "products", "updates": batch });
}
}
db.command({ "update": "products", "updates": batch });
所以这非常好,因为当你仍在迭代列表时,流量和等待线路上的响应实际上已经被最小化了。最好的部分是每500个项目仅发生一次批量更新(通过数学用法)。批量项目的最大大小实际上是16MB的BSON限制,因此您可以根据需要进行调整。
如果您正在开发产品以转移到2.6版本,那么这有一些很好的理由。
我想补充的唯一最后一个脚注是考虑到你正在处理"价格"我试着不使用浮点数学,而是使用整数来寻找一个表格,因为它避免了很多问题。
答案 1 :(得分:0)
这是我把它拉下来的方式。
var result = db.Products.aggregate(
[ { "$unwind":"$Variants" },{"$match":{"Variants.size":"small"}},
{ "$group":
{"_id":"$_id","minprice":
{"$min":"$Variants.price" }}},
{$sort:{ _id: 1}} ] )
result.result.forEach(function(doc) {
db.Products.update( { "_id": doc._id },
{ "$pull": { "Variants" : {
"price":doc.minprice,
"size":"small"
} } } ,
{ $addToSet: { "Variants":{
"price":doc.minprice*1.15,
"size":"small"
} }
);
});