• MongoDB快速copy笔记


    1、聚合 》》 管道的概念和使用,和Java代码的查询实现

    2、BasicQuery、BasicDBObject、BasicDBList(有一种:criteriaVar.andOperator(criteriaList.toArray(new Criteria[0]));)

    3、用Query对象 实现 mongo只返回查询需要的字段,在过滤一些很长的字段时,对性能提示较大

         DBObject dbObject = new BasicDBObject();
            BasicDBObject fieldsObject = new BasicDBObject();
            fieldsObject.put("_id", true);
            fieldsObject.put("imsiList", true);
            fieldsObject.put("fidList", true);
            Query query = new BasicQuery(dbObject, fieldsObject);
            //查询imsiList长度不为0的
            query.addCriteria(Criteria.where("imsiList").not().size(0));
            //。。。

     4、mongo in 查询

    eg:db.getCollection('faceImage').find({"personIds": {$in: ["5d4d4027d7978958761f36ee"]}})

    注意:$in 包含在一对 大括号 里面,in 的条件是个 集合,包含在 一对 中括号 里面

    5、mongo null 查询

    (1)为null或者不存在:db.test.find({"test": null});

    (2)不为null并且存在记录:db.test.find({"test":{"$ne": null}}); 或 db.test.find({"test":{"$ne": null, $exists: true}});

    (3)存在:db.test.find({"test":{$exists: true}});

    (4)不存在(不会返回null的值):db.test.find({"test":{$exists: false}});

    (5)存在且不为null,不为""(空字符串)

    List testList = new ArrayList<>();
    testList .add(null);
    testList .add("");

    queryUser.put("test", new BasicDBObject("$nin", testList));

    6、一次1.8w数据量更新,参考如下:

    场景:男女性别字段的type值(0为男,1为女),导入时反了,现要纠正这1.8万条数据

    以下是比较稳妥的一种方式:比如先将 男type 全更新为9,再将女type改为正确的1,最后将男的改成0

    db.getCollection('dispositionTask').find({})
    
    
    //批量更新
    db.getCollection('dispositionTask').find({"taskStatus": "FINISH"}).forEach(
       function(item){                
           db.getCollection('dispositionTask').update({"_id": item._id},{$set: {"remark": 666}})
       }
    )
       
    //统计数量
    db.getCollection('dispositionTask').find({"taskStatus": "FINISH"}).count({})

    7、最常见的 当前时间 表示法

    //1 字符串 转 Date
    new Date("2019-10-24T10:27:26.312Z")
    //ISODate("2019-10-24T10:27:26.312Z")
    
    //2 Date 转 时间戳
    new Date().valueOf()
    //1571885450433
    
    //3 时间戳 转 Date
    new Date(1570515930*1000)
    //ISODate("2019-10-08T06:25:30Z")
    
    //-->根据输入的 字符串时间 换成 时间戳,且以秒
    new Date("2019-10-24T10:27:26").valueOf() / 1000
    //1571884046

    8、修改字段名称

    db.keyPerson.updateMany(
        {"blackClassId": "liuzhou20190926"},
        {$rename: {"gender": "sex"}},
        false,
        true
    )

    第一个{}是过滤条件,可以为空

    $rename:是关键

    第三个false表示:若根据该过滤条件无法找到匹配的文档时,不插入该文档

    第四个true表示:更新多条

    8、将一个字段的值 更新到 另外一个字段上

    db.getCollection('dispositionTask').find({}).forEach(
        function(doc){
            doc.new_task_name = doc.taskName + "_back";
            doc.placeList.forEach(function(item){
                item.new_pname = item.placeName + "_jbjx";
            })
            db.dispositionTask.save(doc);
        }
    )

    其中,placeList是原文档里面的集合字段,更新集合里面的字段要再forEach一次

    8、根据字段长度统计数据

    db.car.find({$where:"this.carLicense.length >= 8"}).count()
    
    db.car.find({"carLicense": {$exists: true, $regex: /^.{8,}$/}}).count()

    在car表6w数据时,第一种方式平均要1.2s,而第二种只要0.1s多

    8、删除 或 新增 字段名

    db.student.update(
        {"age": {$lte: 30}},
        {$set: {mobilePhone: "123456"}},
        false,
        true
    )

    第一行:查询条件,可置空{}

    第二行:$set,新增 mobilePhone字段,紧跟后面的是初始值

    第三行:false表示批量,true的话,只会执行匹配到的第一条记录

    第四行:false表示如果没有匹配到任何记录的话,会新增一条新的记录;true则不会

    批量删除字段

    db.student.update(
        {"age": {$lte: 30}},
        {$unset: {"mobilePhone": "phone"}},
        true,
        false
    )

    第一行:查询条件,可置空{}

    第二行:$unset,删除 mobilePhone字段,紧跟后面的值不生效,所以用 “” 占位就行

    三、四行同新增

    有一点,如果第三行设置成true,表示只需要执行匹配到的第一条记录,

    如果重复执行该语句的话,不会递推修改匹配到第二条记录的值,即 即使 无限重复执行,也只有第一条匹配到的记录受影响

    9、选择mongo查询返回的字段(一些导出数据场景下会用到)

    //0:指定不导出的字段,默认id是导出的
    db.getCollection('person').find({}, {"_id": 0, "faceUrl": 1, "imsiList": 1, "fidList": 1, "quality": 1, "createTime": 1})
    //可以选择只导出 子对象 的选定字段,也可以选择 子集合 导出指定index的数据 db.getCollection(
    'person').find({}, {"_id": 0, "faceUrl": 1, "fidList": 1, "imsiList": {$slice: 1}, "imsiList.imsi": 1, "imsiList.weight": 1, "quality": 1, "createTime": 1})

    10、管道简单查询

    db.keyPerson.aggregate(
        [
            {$project: {"_id": 0, "name": 1, "age": 1}},
            {$match: {"name": {$regex: /松/}}},
            //{$group: {_id: "$name", num_count: {$sum: 1}}},
            {$group: {_id: "$name", avg_age: {$avg: "$age"}}}
        ]
    )

    $project:需要返回的字段

    $match:过滤条件

    聚合查询参考:https://www.cnblogs.com/zhoujie/p/mongo1.html

    根据车牌统计,并且按数量排序,取前100条:

    数据量是1500w的量,不加 allowDiskUse 选项会报 16945 的错

    db.car.aggregate(
        [
            {$group: {_id: "$carLicense", count: {$sum: 1}}},
            {$sort: {"count": -1}},
            {$limit: 100}
        ],
        {allowDiskUse: true}
    )

    多字段排序:

    db.car.aggregate([
        //"$match":{"create_time": { $gte:1547049600000, $lte:1547135999000} }},
        {
            "$group":{
                "_id":{
                    "carLicense": "$carLicense", 
                    //"color": "$color", 
                    //"type": "$type"
                },
                "carNum":{$sum:1}
            }
        },
        {$sort: {"carNum": -1}}
    ]);

    更多参考:https://xuexiyuan.cn/article/detail/115.html 

    附:子集合 聚合查询 

    其中person数据结构大概如下:

    person: {“id”: "asd", "quality": 1, "imsiList": [{"imsi": "1222", "fnIn": 4}, {"imsi": "2111", "fnIn": 5}]}

    db.person.aggregate([
        {$match: {"quality": 1, "_id" : ObjectId("5dc7a3dca75882022d3ba59a")}},
        {$unwind: "$imsiList"},
        //统计imsiList下,fnIn的总数
        {$group: {_id: "AAA", summmm: {$sum: "$imsiList.fnIn"}}}
    ])
        
    db.person.aggregate([
        {$match: {"quality": 1, "_id" : ObjectId("5dc7a3dca75882022d3ba59a")}},
        {$unwind: "$imsiList"},
        //{$project: {"imsiList": true, "endAge": true}},
        {$group: {_id: "$imsiList.fnIn", count: {$sum: 1}}},
        {$group: {_id: null, imsi不重复数量: {$sum: 1}}}
    ])

    ==》重复字段查询 & 删除重复数据

    根据 cameraCode 分组统计,记录 重复的id,显示重复数量大于1的数据,并且大数据量下,运行在磁盘操作

    db.camera.aggregate([
        {
        $group: {
            _id: {cameraCode: '$key'},
            count: {$sum: 1},
            dups: {$addToSet: '$_id'}
        }
        },
        {
        $match: {count: {$gt: 1}}
        }
    ], 
            {allowDiskUse: true}
    )

    接下来,是根据条件删除重复的数据

    db.delDupKey.aggregate([
    {
        $group: {
            _id: {pipe_id: '$key'},
            count: {$sum: 1},
            dups: {$addToSet: '$_id'}
        }
    },
    {
        $match: {count: {$gt: 1}}
    }
    ], 
            {allowDiskUse: true}
    ).forEach(function(doc) {
        doc.dups.shift();
        db.camera.remove({
            _id: {
                $in: doc.dups
            },
                    "type": 2
        });
    })

    即删除重复数据里面 type=2 的数据;doc.dups.shift()后移一位,后面按id删除

    11、distinct查询 以及 管道方式

    //distinct第一个是要去重的字段,{}里面是过滤条件,注意length
    db.camera.distinct("placeName", {"groupId" : "1"}).length
    
    db.camera.aggregate([
        {$match: {"groupId" : "1"}},
        {$project: {"placeName": true, "name": true}},
        {$group: {_id: "$placeName", count: {$sum: 1}}},
        //第二次$group效果就和上面distinct一样了
        {$group: {_id: null, count: {$sum: 1}}},
        //如果不想显示_id,可以再加一层$project
        {$project: {"count": true, "_id": false}},
    ])

    length:统计distinct的数量直接是这样,不需要加()

    使用这种方法查询时,查询的结果集大于16M 时会查询失败,失败信息如下:
    {“message” : “distinct failed: MongoError: distinct too big, 16mb cap”,”stack” : “script:1:20”}

    使用管道这种查询方式,数据量大时就不会出现如上查询失败的情况,而且这种查询不管是内存消耗还是时间消耗都优于上面一种查询

    12、mongo的简单连表查询

    db.imsiRecord.aggregate([
       {
         $lookup:
           {
             from: "camera",
             localField: "placeId",
             foreignField: "placeId",
             as: "exist_in_imsi"
           }
      }
    ])

    大概就是:select * from  imsiRecord ir left join camera c where ir.placeId = c.placeId

    但是,结果集会在一个集合里面,集合名称就是我们自定义:exist_in_imsi

    ==>如何实现:存在imsiRecord表,但是 不存在 于 camera表,类似 select * from imsiRecord where placeId not in(select placeId from camera) 的功能?

    db.imsiRecord.aggregate([
       {
         $lookup:
           {
             from: "camera",
             localField: "placeId",
             foreignField: "placeId",
             as: "exist_in_imsi"
           }
      },
      { $match : {"exist_in_imsi" : []} }
    ])

    简单的利用mongo的管道功能就OK了,当然,更多的还是需要看官网!

    13、批量替换某字段 里面 的 指定字符

    db.keyPerson.find({
            //'_id': ObjectId("5ddf7711da5015660d5998ab"),
            'faceUrl': {
                    '$ne': null
            },
            'faceUrl': /^http://192.168.31.228:8090/
    }).forEach(function(item) {
            var tmp = String(item.faceUrl)
            //var tmp1 = tmp.match(/^http://116.213.206.162/)
            if (tmp == null) {
                    print(item.faceUrl)
            } else {
                    tmp = tmp.replace(/^http://192.168.31.228:8090/g, "http://192.168.31.228:8099");
            }
            item.faceUrl = tmp;
            db.getCollection('keyPerson').save(item);
    });
  • 相关阅读:
    前端笔记之JavaScript(六)让人头疼的正则表达式
    前端笔记之JavaScript(五)关于数组和字符串那点事
    前端笔记之JavaScript(四)关于函数、作用域、闭包那点事
    前端笔记之JavaScript(三)关于条件判断语句、循环语句那点事
    前端笔记之JavaScript(二)关于运算符&初识条件判断语句
    前端笔记之CSS(下)浮动&BFC&定位&Hack
    前端笔记之CSS(上)语法&文本属性&块/行内元素&选择器&盒模型
    artTemplate--使用artTemplate时,由于json对象属性有数字命名格式 导致调用报错 syntax error
    多线程--做单元测试时,使用线程池发现并没有运行指定代码,直接跳过
    JSP-导入taglib 出现classNotFound异常
  • 原文地址:https://www.cnblogs.com/zz-3m23d-begining/p/11045014.html
Copyright © 2020-2023  润新知