酉卒之子

导航

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);
});

posted on 2021-06-23 14:51  酉卒之子  阅读(299)  评论(0编辑  收藏  举报