mongodb常用操作符

MongoDB操作符

MongoDB介绍

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
如下这种结构

MongoDB命令行简单操作

假设存在数据库名称为database
并且存在一个集合为collection
集中collection中有如下数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
{
"name": "Daniel",
"age": 24,
"job": "it",
"hobby": "travel"
},
{
"name": "Mike",
"age": 18,
"job": "student",
"hobby": "travel"
}
]
  • 创建数据库或使用数据库
    use database

  • 删除数据库
    db.dropDatabase()

  • 查看数据库列表
    show dbs

  • 创建集合
    执行use操作后
    db.collection.opertion
    没有创建集合的语法,直接对指定集合进行操作就会创建该集合

  • 查看当前数据库的集合列表
    show collections

  • 删除集合
    db.collection.drop()

  • 查找

  1. 执行find命令
    db.collection.find({ hobby: "travel" })
    得到以下结果

find命令会找到符合查询条件的所有结果
可以在后面跟上.pretty()来让数据展示更美观。
后面跟.count()返回查找到的数量
后面跟.sort()返回排序后的数据
比如这样db.collection.find({ hobby: "travel" }).sort({ age: 1 })1表示升序,2降序

  1. 执行findOne命令
    db.collection.findOne({ hobby: "travel" })

    findOne只会找到符合条件的第一条
  • 删除
  1. 执行deleteOne命令
    db.collection.deleteOne({ hobby: "travel" })
    得到以下结果

    deleteOne命令会删除符合查询条件的第一条数据

  2. 执行deleteMany命令
    db.collection.deleteMany({ hobby: "travel" })
    deleteMany命令会删除符合查询条件的所有数据

  • 插入
  1. 执行insertOne命令
    db.collection.insertOne({ "name": "Rick", "age": 32, "job": "teacher", "hobby": "sport" })
    insertOne命令可以添加一条数据到集合中
    他有一个可选参数{ writeConcern },写入策略,默认为 1,即要求确认写操作,0 是不要求。

  2. 执行insertMany命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
db.collection.insertMany([
{
"name": "Jack",
"age": 12,
"job": "student",
"hobby": "watch tv"
},
{
"name": "Mary",
"age": 8,
"job": "student",
"hobby": "book"
}
])

insertMany允许同时插入多条数据到集合中
他有一个可选参数{ writeConcern, ordered },writeConcern意义同上,orderd表示是否按顺序写入,默认 true,按顺序写入。

  • 更新
  1. 执行updateOne命令
    db.collection.updateOne({ "name": "Mike" }, { $set: { "age": 20 } })
    updateOne命令可以更新匹配条件的第一条数据

  2. 执行updateMany命令
    db.collection.updateMany({ "hobby": "travel" }, { "hobby": "watch tv" })
    updateMany命令可以更新匹配条件的所有数据

还有几个可选参数,可自行百度

MongoDB操作符

接下来介绍的是MongoDB中一些常用的操作符,暂时将操作符分为更新和查找两类。

更新操作符

$inc

对一个字段增加指定数量,且字段的值类型为数字

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$inc": { age: 100 }
})

当然可以通过指定数字值为负数实现递减操作。

$set

这是相当常见的操作符,表示设置指定的key

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$set": { age: 1000 }
})

上述将nameMike的字段的age字段设置为1000
如果key不存在的话则创建
当然也可以同时设置多个值,但是需要注意的是如果修改的值之前是一个对象或一个数组的话会整个覆盖掉该值。具体的修改方法可以参照下方的具体实例。

$unset

将某一个字段删除

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$unset": { "hobby": "" }
})

上述将nameMike的字段的hobby字段删除,如果不存在该字段则不进行操作

$push

对某一字段进行内容追加,只能对数组字段进行操作(否则会报错),不存在则直接设置为空数组并添加

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$push": { "like": "book" }
})

上述将nameMike的字段的like字段设置为[ "book" ]

$pushAll

类似上面的$push操作符,但是接收的值时一个数组,表示可同时追加多个值,同样是对数组字段进行操作

1
2
3
4
5
db.collection.updateOne({
"name": "Jack"
}, {
"$pushAll": { "like": [ "tv", "sport" ] }
})

上述紧接前面的操作,向like字段中继续追加了tvsport
不过似乎在高版本mongodb已经取消了这个操作符,有待考证。

$addToSet

类似上面的$pushAll操作符,不同的是,当且仅当该值在字段中不存在时添加,相当于是自动做了去重。

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$addToSet": { "like": [ "tv", "hamberger" ] }
})

继续上面的like添加数据,因为上面添加过tv字段,所以再次添加被忽略
当然此操作符添加的值不一定是数组,也可以这样
$addToSet: { "like": "hamberger" }

$pop

$pop操作符相反,表示删除指定字段的第一个或最后一个值,同样只能是数组

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$pop": { "like": 1 }
})

上述表示删除like字段的最后一个值。
1表示最后一个值,-1表示第一个值

$pull

表示从某一字段中删除指定的值,针对数组

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$pull": { "like": "hamberger" }
})

上述将nameMike的字段的like数组中的hamberger字段删除

$pullAll

类似$pull操作符,不同的是可以同时删除多个值

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
"$pullAll": { "like": [ "hamberger", "book" ] }
})

上述删除了nameMike字段的like中的hambergerbook

$rename

这个操作符表示对之前设置过的字段进行重命名,设置的是key

1
2
3
4
5
db.collection.updateOne({
"name": "Mike"
}, {
$rename: { "like": "dislike" }
})

上述将like字段修改为了dislike名称。

查找操作符

下面介绍的,是常用的查询操作符🌰

$all

查找字段中包含指定内容的值,且需要包含全部指定的值,针对数组型字段

1
2
3
db.collection.find({
"like": { "$all": [ "hamberger", "book" ] }
})

上述能查找到nameMike字段,但是无法查找到其他字段,因为他们无法完全满足查询条件。

$gt

查找大于(great then)指定值的字段

1
2
3
db.collection.find({
"age": { "$gt": 18 }
})

上述查找age大于18的字段,不包含18
日期也可直接那这个进行比较

$gte

表示不小于指定值,也就是大于等于

1
2
3
db.collection.find({
"age": { "$gte": 20 }
})

上述查找age不小于20的字段,所以包括等于20的字段

$lt

与上面的$gt操作符相反,表示小于(less then)指定值

1
2
3
db.collection.find({
"age": { "$lt": 20 }
})

上述查找age小于20的字段,且不包含20

$lte

表示不大于指定值,也就是小于等于

1
2
3
db.collection.find({
"name": { "$lte": 18 }
})

上述查找age小于18的字段,且包含18

$in

查找存在指定数组中值得项,与$all不同的是,字段只需要满足其中任意一项即可

1
2
3
db.collection.find({
"age": { "$in": [ 18, 20 ] }
})

上述可以找到所有在age字段等于1820的数据

$nin

与上面的$in操作符相反,表示查找不存在指定数组中的值的项

1
2
3
db.collection.find({
"like": { "$nin": [ "tv" ] }
})

上述查找like字段中不存在tv的项

$ne

有相等就会有不相等,这个操作符就是查找不等于指定值得项,相当于只有一项的$nin

1
2
3
db.collection.find({
"like": { "$ne": "book" }
})

上述查找like字段中不存在book的项

$and

查找同时满足所有指定条件的项,并且至少需要包含两个条件

1
2
3
4
5
6
7
8
9
10
db.collection.find({
"$and": [
{
"name": "Mike"
},
{
"age": 18
}
]
})

上述查找nameMike并且age20的字段

$nor

与上面的$and相反,表示查找同时不满足所有指定条件的项,同样至少需要包含两个条件

1
2
3
4
5
6
7
8
9
10
db.collection.find({
"$nor": [
{
"name": "Mike"
},
{
"age": 18
}
]
})

上述查找name不为Mike并且age不等于18的数据

$not

指定不能满足指定条件的数据项,此操作符只能包含一个条件,而且它无法单独完成查询,需要与其他操作符配合一起使用。

1
2
3
4
5
db.collection.find({
"age": {
"$not": { "$gt": 18 }
}
})

上述查找age字段小于等于18的数据项,当然像例子这样的情况也可以直接使用$lte操作符完成。

$or

表示查找能至少满足一个条件的项,并且需要至少包含两个筛选条件

1
2
3
4
5
6
7
8
9
10
db.collection.find({
"$or": [
{
"name": "Mike"
},
{
"age": 20
}
]
})

上述表示查找nameMike或者age20的数据项

$exists

此操作符用于字段的key的判断,表示查找是否存在否字段key的数据项,可选值为truefalse,选择true表示存在,false则不存在指定字段的项

1
2
3
db.collection.find({
"name": { "$exists": true }
})

上述查找存在name字段的数据项

$mod

表示查找满足计算结果的数据项,此操作符为取模

1
2
3
db.collection.find({
"age": { "$mod": [ 3, 0 ] }
})

上述表示age字段的值对3取模等于0的值。

$type

表示选择指定数据类型的数据项

1
2
3
db.collection.find({
"name": { "$type": "string" }
})

上述查找name字段值类型为string的数据项
此操作符表示能查找对应的数据类型的数据项,它也有对应的代码,如下所示

Double: 1
String
Object 3
Array 4
Binary data 5
Undefined 6 已废弃。
Object id 7
Boolean 8
Date 9
Null 10
Regular Expression 11
JavaScript 13
Symbol 14
JavaScript (with scope) 15
32-bit integer 16
Timestamp 17
64-bit integer 18
Min key 255 Query with -1.
Max key 127

$regex

就是字面意思,使用正则表达式来匹配字段

1
2
3
db.collection.find({
"name": { "$regex": /mike/, "$options": "i" }
})

上述匹配name字段值包含mike(不区分大小写是因为配置了$options)的数据项
$options表示正则表达式的修饰符,其他的还有i(不区分大小写),g(全局匹配),m(多行匹配),s(.包含换行符\n)
当然直接使用正则表达式也是可以的。

$where

有些情况下普通方法很难做出筛选,可以使用此操作符用javascript语法来进行筛选

1
2
3
db.collection.find({
"$where": "this.name='Jack'&&this.like.some(key => key == 'hamberger')"
})

上述查找nameJacklike字段包含hamberger值得数据项
它甚至可以直接写一个函数{ function() { return this.name == 'Jack' && this.like.some(key => key == 'hamberger') } }
注意
虽然这种方法可以有效的解决一些问题,但是还是尽量不要使用这个操作符,因为它会将MongoDB里面保存的BSON数据变为JavaScript的语法结构,这样的方式不方便使用数据库的索引机制。

$elemMatch

此操作符用于对类似一个嵌套数组对象来进行多条件的查询

上述查找了like字段数组中typeeat并且targethamberger的数据项

$slice

将数据中的数组字段做切割,选出一段选区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 基本查询
db.collection.find({}, {
like: {
$slice: [1, 1]
}
})
//聚合查询
db.collection.aggregate([
{
$project: {
like: {
$slice: [ "$like", 1, 1 ]
}
}
}
])

以上两种方法都能取出对应的数组项的第一条,两个数字分别代表:起始的索引、切割的数量

  • 基本查询
  • 聚合查询

相关实例

讲完了操作符,这里简单讲几个之前在实践当中碰到的一些问题,以及解决方法,欢迎各位参考。

查找或修改数组中嵌套的对象的属性

假设databasecollection中存在以下数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
"name": "Mike",
"age": 18,
"job": "student",
"like": [
{
"type": "eat",
"target": "hamberger"
},
{
"type": "sport",
"target": "running"
}
]
},
{
"name": "Jack",
"age": 50,
"job": "teacher",
"like": [
{
"type": "eat",
"target": "vegetable"
},
{
"type": "sport",
"target": "baseball"
}
]
}
]

普通情况下无法直接选中对应数组对象的属性,但是mongodb中支持.来选择数组对象中的属性

  • parent_field.child_field
    比如像上面的like字段选择target=vegetable
    db.collection.find({ "like.target": "vegetable" })

    修改多层嵌套的数组对象

有时候不止会有一层嵌套,多层嵌套上面的方法不适用,虽然这种存储方式不太常见,但是也可以解决
假设有如下的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[
{
"name": "Jack",
"like": [
{
type: "eat",
target: [
{
name: "hamberger",
price: 100
},
{
name: "salad",
price: 200
}
]
}
]
}
]

//执行更新操作
db.collection.updateOne({ name: "Jack" }, { $set: { "like.$[stepone].target.$[steptwo].price" : 200 } }, {
arrayFilters: [
{
"stepone": {
"$type": "object"
},
"stepone.type": "eat"
},
{
"steptwo": {
"$type": "object"
}
}
]
})

上述操作是选择上面数据中like字段的typeeat并且target数组中的namehamberger的价格price改成了200
updateOne的第三个参数用户定义第二参数中用到的嵌套名称的筛选条件,并且它的名称定义为以小写字母开头的字母数字字符串

结束

MongoDB的操作符以及命令远不止这些,有兴趣的可以自行去MongoDB官网查找学习,本人也会在后续的实践学习中继续更新。😸


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!