MongoDB常用SQL

基本查询

简单查询

find({"comId":"1012", "group":123})

包含:$in

find({name: {$in:["zhangsan", "lisi"]}})             #in是匹配[]中任意一个值即可
find({name: {$in:[/^zh/, /si$/]}})                   #查询name字段中,以zh开头或者si结尾的
find({"procTree.pid": {$in: [2011, 2012]}})          #当字段为一个数组时,数组中的任一元素匹配[]中任意一个值即可

匹配所有:$all

find({"procTree.pid": {$all: [2011, 2012]}})      #all是必须匹配[]中所有值才算匹配

范围查询

操作符:$gte:大于等于 $lte:小于等于 $eq:等于

find({age: {$lt:20}})     #查询age<20的
find({age: {$gt:20}})     #查询age>20的
find({tags: {$ne:null}})  #查询tags不为空的

数组中元素个数:$size

find({"procTree": {$size: 2}})    #查询procTree数组中有两个元素的

字段是否存在:exists 

find({"detections.detectionName":{$exists:true}})   #子文档中的detectionName字段是否存在
find({"elementIds.3":{$exists:true}})   #文档中的elementIds字段(数组)索引为的3的数据是否存在(等效于数组长度是否>3

模糊查询

find({"comId":/11/})              #查询comId包含11的(全模糊匹配)
find({"comId":/^11/})             #前缀匹配
find({"comId":{$regex:"^11"}})                  #前缀匹配         
find({"comId":{$regex:"12$", $options:"i"}})    #后缀匹配,忽略大小写

“非”查询:$not、$nin

$not后面只能接表达式,比如正则、$gt等

find({name: {$not: /zhang/}})               #查询name字段,不是以zhang开头的
find({age: {$not: {$gt: 30}}})              #查询age字段,不是大于30的,即小于等于30的
find({name: {$nin: [/^zh/, /si$/]}})        #查询name字段,不是以zh开头或者si结尾的
find({name: {$nin: ["zhangsan", "lisi"]}})  #查询name字段,既不等于zhangsan也不等于lisi的

投影查询

find({"comId":{$regex:"12$"}, {"comId":1, "detectType":1, "group":1, "_id":0})     #1表示显示,0表示不显示。_id默认显示,要不想显示,需要设置为0

分页查询

find().skip(3).limit(2)            #跳过3条数据,然后返回最多2条数据

查询数据条数:count()

find({"comId":"1012"}).count()                #返回find过滤后的数据条数
find({"comId":"1012"}).limit(2).count(true)   #返回2条数据。使用了limit的sql,如果直接使用count(),里面参数不是true或者非0的,那返回的结果就是全部的(跟上面一样)

排序:sort()

find({"comId":"1012"}).sort({"createTime":-1})   #根据createTime排序。1是升序,-1是降序

 去重:distinct()

distinct("modelType")

 

聚合查询

计数、求和:$sum

aggregate([{$group: {_id:null, cou: {$sum:1}}}])                #相当于select count(*) cou from dev
aggregate([{$group: {_id:null, totalAge: {$sum:"$age"}}}])      #相当于select sum(age) totalAge from dev
aggregate([{$group: {_id:"$name", totalAge: {$sum:"$age"}}}])   #相当于select name _id, sum(age) totalAge from dev group by name

条件筛选:$match

aggregate([{$match: {age: {$gt:20}}}, {$group: {_id:null, cou: {$sum:1}}}])                    #相当于select count(*) cou from dev where age>20
aggregate([{$group: {_id:"$name", totalAge: {$sum:"$age"}}}, {$match:{totalAge: {$gt:25}}}])   #相当于select name _id, sum(age) totalAge from dev group by name having totalAge>25

最大、最小、平均值:$max、$min、$avg

aggregate([{$group: {_id:null, maxAge: {$max:"$age"}}}])        #相当于select max(age) maxAge from dev
aggregate([{$group: {_id:null, minAge: {$min:"$age"}}}])        #相当于select min(age) minAge from dev
aggregate([{$group: {_id:null, avgAge: {$avg:"$age"}}}])        #相当于select avg(age) avgAge from dev

统计结果返回数组:$push、$addToSet

aggregate([{$group: {_id:"$name", ageArr: {$push:"$age"}}}])        #按照name分组,使用数组返回组内所有的age值(不会去重)
aggregate([{$group: {_id:"$name", ageArr: {$addToSet:"$age"}}}])    #按照name分组,使用数组返回组内所有的age值(会去重)

数组字段拆分:$unwind

注意:文档中没有tags字段的不会显示

aggregate([{$unwind:"$tags"}])   #将集合中所有tags字段(数组)拆分成单个显示。比如某个文档中tags有三个元素,则会拆分成三条数据

聚合投影查询  $project

注意:$project后面的投影查询,字段后面既可以使用变量(如"$name"),也可以使用数字(0或1)。不过,如果想字段名称取别名,则只能使用变量

aggregate([{$unwind:"$tags"}, {$project:{_id:0,name:"$name", tags:1}}])       #将tags数组的内容拆分,并只显示name和tags键

字符串操作   $project

注意:$concat中的字段变量只能为字符串类型

aggregate([{$project:{_id:0, Name:{$toUpper:"$name"}}}])                                       #name的值转为大写并取别名Name。转小写:toLower
aggregate([{$unwind:"$tags"}, {$project:{_id:0, nameTags:{$concat:["$name", "-", "$tags"]}}}]) #将tags数组的内容拆分,name字段和tags字段拼接并取别名nameTags
aggregate([{$project:{_id:0, namePrefix:{$substr:["$name", 0, 3]}}}])                          #只显示name字段前三个字符并取别名namePrefix

关联查询 $lookup

场景:关联查询多个表。主表qtasset_mo_host,外键_agent_id、从表app_ids_config,关联键agent_id

db.qtasset_mo_host.aggregate([
    {$lookup: {
           from: "app_ids_config",
           localField: "_agent_id",
           foreignField: "agent_id",
           as: "config"
         }},
   {$match:{
       _agent_id:{$in: ["a245382b8bc9c82c", "b69cfdffb5b1a99f", "ad4b436be13ae367", "2301fc678fd53886"]},
       "config.host_enable": true
   }},
   {$project : {
         _agent_id: 1,
         "config.host_enable": 1
   }}
])

 

日期处理

MongoDB中的时间会比系统当前时间少8h。因为默认是UTC时区,而中国的时区是东八区,比UTC快8h

插入日期

insert({time:new Date()})                         #会比系统时间少8h
insert({time:new Date("2020-05-20T10:30:46Z")})   #必须严格按照日期格式,否则插入的日期或时间会有问题
insert({time:ISODate("2020-05-20 10:30:46")})     #ISODate为内置函数,不用完全按照上面的日期格式,它会自动转成正确的

日期过滤查询

find({time: {$eq:new Date("2020-05-20T10:30:46Z")}})  
find({time: {$gt:ISODate("2020-05-20 10:30:46")}})

日期处理查询

注意:$dayOfWeek:星期日为1,星期六为7,$week:计数从0开始

aggregate([{$match:{time: {$ne:null}}},{$project:{year:{$year:"$time"}, month:{$month:"$time"}, day:{$dayOfMonth:"$time"}}}])   #查询time字段的年、月、日
aggregate([{$match:{time: {$ne:null}}},{$project:{hour:{$hour:"$time"}, minute:{$minute:"$time"}, second:{$second:"$time"}, milSec:{$millisecond:"$time"}}}])   #查询time字段的时、分、秒、毫秒
aggregate([{$match:{time: {$ne:null}}},{$project:{星期:{$dayOfWeek:"$time"}, 全年第几周:{$week:"$time"}, 全年第几天:{$dayOfYear:"$time"}}}])

显示自定义日期格式

aggregate([{$match:{time: {$ne:null}}},{$project:{myTime:{$dateToString:{format:"%Y-%m-%d %H:%M%S", date:"$time"}}}}])

 

新增

语法格式:insert({新增数据})

insert({"_id":1, name:"zhangsan"})                   #单条新增
insertMany([{"_id":1, name:"zhangsan"}, {"_id":2, name:"lisi"}])    #批量新增

 

更新

语法格式:update({查询条件}, {更新内容}, {更新参数(可选)})

update({name:"zhangsan"},{age:100})                          #文档更新成指定的内容,即更新后文档只有_id和age字段了
update({name:"zhangsan"},{$inc:{age:1}})                     #将age的值+1
update({name:"zhangsan"},{$set: {age:200}})                  #加了$set,更新或新增指定字段,不会改变文档其它字段(只会更新第一条数据)
update({name:"zhangsan"},{$set: {age:200}}, {multi:true})    #批量更新或新增指定字段 
update({name:"zhangsan"},{$unset: {age:1}}, {multi:true})    #加了$unset,删除指定字段,不会改变文档其它字段

引用自身的值进行更新

场景:将docker_detect_dashboard中createTime字段的值缩小1000倍

db.docker_detect_dashboard.find({"modelType":"abnormal_model_event", "createTime":{$gt: NumberLong("10000000000")}}).forEach(function(i){
    db.docker_detect_dashboard.update({_id: i._id},
    {$set: {"createTime": i.createTime/1000}}
)
})

两个表联表查询,然后更新其中一个表的字段

场景:detections 为表 ids_incident 的子文档,当 ids_incident 和 ids_detection 中的条件匹配上时,更新 ids_incident.detections 子文档,为子文档增加字段 detectionName 并对其赋值

db.ids_detection.find({comId:"123456"}).forEach(function(i){
    db.ids_incident.updateMany({incidentId: i.incidentId, "detections.detectionId":i.detectionId},
    {$set: {"detections.$.detectionName": i.detectionName}})
})

修改字段名称

db.ids_detection.update({}, {$rename:{"filePath":"fpath"}}, false, true)         #将filePath改为fpath

查询并修复,原子操作

场景:需要先查询 ids_scan_result 中 totalReportTimes 字段,然后再对该字段进行计算(比如+1操作),最后再赋值给该字段,整个过程一定要串行执行(也可以通过加锁实现)

db.ids_scan_result.findAndModify({
    query:{
        baseJobId:"98e7a9f1-aa59-4af4-9310-6c8e794643c8"
    },
    update: {
        $inc: {totalReportTimes: 1},
        $set: {actualReportTimes: 2}
    }
})

修改嵌套子文档数组中的多个元素

场景:app_ids_detect_config 中 method_switches 字段为一个对象数组,对象中只有两个字段 detection_method 和 enable ,需要将 detection_method 的值为  CTN 前缀的元素的enable改为true

db.app_ids_detect_config.updateMany({
    "platform_type": {
        $in: ["LINUX_SERVER", "LINUX_PC"]
    },
    "method_switches.detection_method": /CTN/
}, {
    $set: {
        "method_switches.$[a].enable": true
    }
}, {
    arrayFilters: [{
        "a.detection_method": /CTN/
    }]
})

说明:如果只需要修改数组中的一个元素,那可以不需要arrayFilters,如果需要修改多个元素,则必须加上arrayFilters。arrayFilters过滤后的值将作为上面$set中的下标。

 

删除

语法格式:remove({查询条件})

remove({})                #删除所有数据
remove({name:"zhangsan"}) #删除指定条件的数据

 

索引

创建索引

语法格式:createIndex({创建索引的键: 排序规则}, {创建索引参数(可选)})

createIndex({name:1})       #为name创建正序索引
createIndex({name:1, age:-1},{name:"idx_name_age"})    #为name和age创建复合索引,索引名称为idx_name_age
createIndex({name:1, age:1},{name:"idx_name_age", unique:true})   #创建唯一索引

排序规则:1:正序  -1倒序

索引参数:

参数 数据类型 默认值 功能
background Boolean false 后台建立索引,创建索引时不阻塞其它操作
expireAfterSeconds Integer   指定索引过期时间
name String   指定索引名称,如果未指定,MongoDB会生成一个索引字段名称_排序顺序的名称
sparse Boolean false 对文档中不存在的字段数据不启用索引
unique Boolean false 创建唯一索引

 注意点:如果集合中字段索引已存在,再次为该字段创建索引不会生效

查看索引

getIndexes()              #查看集合中所有索引信息
getIndexKeys()            #查看集合中所有的索引键
totalIndexSize(可选参数)   #查看集合中索引的大小,单位字节。参数说明:可选参数为0、false或者空,显示所有索引的总大小,其它值显示每个索引的大小及总大小

删除索引

dropIndex("idx_name")    #删除索引名称为idx_name的索引
dropIndexes()            #删除全部索引,_id键的索引除外

重建索引

使用场景:数据大量变化后,可以使用重建索引构建更高效的B-Tree,优化索引查询效率

过程说明:重建索引是删除原索引重新创建的过程,不建议反复使用

reIndex()

 

posted @ 2021-06-21 20:40  仅此而已-远方  阅读(942)  评论(0编辑  收藏  举报