NoSQLBooster for MongoDB 中跨库关联查询

本文分享了在MongoDB中进行跨库关联查询的优化经验,从单条查询到批量查询,再到批量更新,逐步提高处理大量数据时的查询与更新效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

​ 使用 MongoDB 是我们常常会遇到一些特殊的需求需要跨库关联查询,比如订单明细缺商品重量需要补商品重量,而商品重量数据又在商品库中,这事就需要跨库关联操作,示例代码如下:

// 使用 order 库,注意语句后面不要加分号
use order
 
var 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 order
 
var 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 order
 
var 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值