? 使用 MongoDB 是我們常常會遇到一些特殊的需求需要跨庫關聯查詢,比如訂單明細缺商品重量需要補商品重量,而商品重量數據又在商品庫中,這事就需要跨庫關聯操作,示例代碼如下:
// 使用 order 庫,注意語句后面不要加分號
use ordervar count = 0;
db.order_detail.find({"store_code":"110"}).forEach(function(_order){// 在 goods 庫查詢 item 集合var item = db.getSiblingDB("goods").item.findOne({"barcode":_order.barcode});if(item){db.order_detail.update({_id:_order._id},{$set:{"weight":item.weight}},false,true);count++;}else{print("商品不存在, 條碼:" + _order.barcode);}
});
print("更新條數:" + count);
注意:跨庫查詢時必須使用 admin 庫來授權連接操作。
? 上面示例的代碼,數量不多時還能勉強湊合著使用。當數據量達到上萬條數據時就顯示非常非常慢。因為更新一條數據需要單條 findOne 再單條 update。因此得優化,將單條查詢改批量查詢(緩存查詢結果),示例代碼如下:
use ordervar count = 0;
var items = {};
db.getSiblingDB("goods").item.find({"store_code":"110"}).forEach(function(_item){// items 當做 map 使用, key 商品條碼(barcode)items[_item.barcode] = _item;
});
db.order_detail.find({"store_code":"110"}).forEach(function(_order){var item = items[_order.barcode];if(item){db.order_detail.update({_id:_order._id},{$set:{"weight":item.weight}},false,true);count++;}else{print("商品不存在, 條碼:" + _order.barcode);}
});
print("更新條數:" + count);
? 經過將單條查詢改成批量查詢后執行效率確實提升不少,但是還是覺得慢,還得繼續優化,將單條更新改成批量更新,示例代碼如下:
use ordervar count = 0;
var items = {};
db.getSiblingDB("goods").item.find({"store_code":"110"}).forEach(function(_item){items[_item.barcode] = _item;
});
var ops = [];
db.order_detail.find({"store_code":"110"}).forEach(function(_order){var item = items[_order.barcode];if(item){var f = {_id:_order._id};var upd = {$set:{"weight":item.weight}};ops.push({"updateMany":{"filter":f, "update":upd, "upsert":false}});count++;}else{print("商品不存在, 條碼:" + _order.barcode);}if(count > 0 && count % 1000 == 0){// 批量更新, ordered:false 無序操作db.order_detail.bulkWrite(ops, {ordered:false});ops = [];print("更新條數:" + count);}
});if(ops.length > 0){db.order_detail.bulkWrite(ops, {ordered:false});
}
print("更新完成,更新總條數:" + count);
批量操作參見: http://www.xuexiyuan.cn/article/detail/173.html
原文地址:https://xuexiyuan.cn/article/detail/204.html