基本概念
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。MongoDB中的记录是一个文档,它是由字段和值对组成的数据结构。文档类似于JSON对象,存储在集合中。集合类似于关系数据库中的表。
MongoDB 将数据记录存储为 BSON 文档。BSON 是JSON文档的二进制表示,但它包含的数据类型比 JSON 多
shell 中使用
创建数据库
use 数据库名
如果数据库不存在,则创建数据库,否则切换到指定数据库。
db.createCollection(集合名称 , 可选参数)
创建集合,可选参数如下:
db.createCollection( <name>,
{
capped: <boolean>,
timeseries: { // Added in MongoDB 5.0
timeField: <string>, // required for time series collections
metaField: <string>,
granularity: <string>
},
expireAfterSeconds: <number>,
autoIndexId: <boolean>,
size: <number>,
max: <number>,
storageEngine: <document>,
validator: <document>,
validationLevel: <string>,
validationAction: <string>,
indexOptionDefaults: <document>,
viewOn: <string>, // Added in MongoDB 3.4
pipeline: <pipeline>, // Added in MongoDB 3.4
collation: <document>, // Added in MongoDB 3.4
writeConcern: <document>
}
)
复制代码
也可以直接在集合中插入相应数据,会自动创建集合,如:db.user.insert({name:’admin’})
仅仅使用 use <数据库名> 切换到对应数据库后 show dbs,并不会找到刚创建的那个数据库,需要向库中添加一些数据之后才能查询到,默认使用的test库。
删除数据库
删除集合(表),如果集合是最后一个被删除后,通过show dbs 也看不到对应的库
db.集合名称.drop()
删除数据库,切换到指定库中进行相应删除操作
db.dropDatabase()
数据CRUD
ObjectId(<hexadecimal>)
返回一个长度位24的字符串(并不是字符串,实际上是mongo里面特有的一种类型)
- 一个 4 字节的时间戳值,代表 ObjectId 的创建,以 Unix 纪元以来的秒数为单位
- 一个 5 字节的随机值
- 一个 3 字节递增计数器,初始化为随机值
插入时如果该集合当前不存在,则插入操作将创建该集合;存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略了该 _id 字段,MongoDB 驱动程序会自动为该字段生成一个ObjectId_id
数据插入
db.collection.insertOne()
将单个文档插入到集合中
db.user.insertOne({
name: "test1",
age: 18,
grade: 1,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
})
复制代码
db.collection.insertMany()
将多个文档插入到一个集合中
db.user.insertMany([
{
name: "test1",
age: 18,
grade: 1,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
}
])
复制代码
db.collection.insert()
将单个文档或多个文档插入到集合中
db.user.insert({
name: "test1",
age: 18,
grade: 1,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
});
db.user.insert([
{
name: "test1",
age: 18,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
}
]);
复制代码
数据删除
db.collection.deleteOne()
最多删除一个与指定过滤器匹配的文档,即使多个文档可能与指定的过滤器匹配
db.user.deleteOne({ "_id": ObjectId("611dc577166b0506cd3d6cb0") })
复制代码
db.collection.deleteMany()
删除与指定过滤器匹配的所有文档
db.user.deleteMany({ age: 18 })
复制代码
db.collection.remove()
删除单个文档或与指定过滤器匹配的所有文档
db.user.remove({ age: 18 });
db.user.remove({});
复制代码
db.user.remove({}) 这个操作不等于 drop() 方法,要从集合中删除所有文档,使用drop()方法删除整个集合(包括索引),然后重新创建集合并重建索引更有效。
数据修改
db.collection.updateOne(<filter>, <update>, <options>)
配合 $set
等操作符来更新单个文档的部分属性
db.user.updateOne({
_id: ObjectId("611e0083b3e0ed299caa7183")
}, {
$set: {
name: 'newName'
}
})
复制代码
db.collection.updateMany(<filter>, <update>, <options>)
更新与集合的指定过滤器匹配的所有文档
db.user.updateMany({
grade: 1
}, {
$set: {
grade: 2
}
})
复制代码
db.collection.update(<filter>, <update>, <options>)
配合 $set
等操作符来更新单个或者多个(取决于options里面的 multi
是否为 true
,默认为 false
)文档的部分属性
db.user.update({
grade: 1
}, {
$set: {
grade: 2
}
}, {
multi: true,
})
复制代码
db.collection.replaceOne(<filter>, <update>, <options>)
覆盖式更新,不能只更新某一个字段,用新的文档替换匹配到的那个文档
db.user.replaceOne({
_id: ObjectId("611e0083b3e0ed299caa7183")
}, {
name: "newDocument",
age: 18,
grade: 1,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
})
复制代码
以上几个方法中 <options>
参数中的 upsert
属性如果为 true
时(默认为false
),此方法在<filter>
没有匹配到文档时,会将<update>
作为新的文档插入到集合中,如:
db.user.replaceOne({
_id: ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa")
}, {
name: "updateForCreate",
age: 18,
grade: 1,
parents: ["test1P1", "test1P2"],
description: {
hobby: "sleep",
skill: ["sing", "jump", "rap", "basketball"],
score: 59,
}
}, {
upsert: true
})
复制代码
数据查询
db.collection.find(<filter>)
基于以下5条数据做查询操作
db.user.insertMany([
{
"name": "a",
"age": 18,
"grade": 1,
"parents": [
"aP1",
"aP2"
],
"hobby": "coffee-shop-cake",
"description": {
"skill": [
"sing"
],
"score": 88
}
},
{
"name": "b",
"age": 18,
"grade": 1,
"parents": [
"aP1",
"aP2"
],
"hobby": "java-coffee",
"description": {
"skill": [
"jump"
],
"score": 99
}
},
{
"name": "d",
"age": 19,
"grade": 2,
"parents": [
"dP1",
"dP2"
],
"hobby": "eat-run",
"description": {
"skill": [
"basketball"
],
"score": 59
}
},
{
"name": "c",
"age": 19,
"grade": 1,
"parents": [
"cP1",
"cP2"
],
"hobby": "sleep",
"description": {
"skill": [
"rap"
],
"score": 59
}
},
{
"name": "e",
"age": 20,
"grade": 3,
"parents": [
"eP1",
"eP2"
],
"hobby": "sleep-java",
"description": {
"skill": [
"sing",
"jump",
"rap",
"basketball"
],
"score": 69
}
}
])
复制代码
查询所有数据
db.user.find();
db.user.find({});
复制代码
且(&&)查询
查询 grade 等于 1 并且 age 等于 19 的数据:
db.user.find({ grade: 1, age: 19 });
复制代码
db.user.find({ $and: [{ grade: 1 }, { age: 19 }] });
复制代码
或(||)查询
查询 age 等于 18 或 19 的数据:
db.user.find({ $or: [{ age: 18 }, { age: 19 }] });
复制代码
db.user.find({ age: { $in: [18, 19] } });
复制代码
模糊查询
在模糊查找之前需要存在索引否则会报text index required for $text query
的错误,可以通过
db.collection.createIndex( <key and index type specification>, <options> )
创建索引db.collection.getIndexes()
查询索引db.collection.dropIndex(index)
删除索引
db.user.dropIndex("hobby_text")
db.user.createIndex({ hobby: "text" })
复制代码
创建好索引之后使用$text
操作符进行模糊查找,参数格式如下:
{
$text:
{
$search: <string>,
$language: <string>,
$caseSensitive: <boolean>,
$diacriticSensitive: <boolean>
}
}
复制代码
查询索引字段里面包含 coffee 的数据:
db.user.find({ $text: { $search: "coffee" } })
复制代码
比较运算符查询
$eq
:相等(==)$ne
:不等(!=)$gt
:大于(>)$lt
:小于(<)$gte
:大于等于(>=)$lte
:小于等于(<=)$in
:存在$nin
:不存在
查询 age 大于等于 18 小于等于 19,parents 中包括 “aP1” 或 “cP1” 的但是 name 不为 “b” 的数据:
db.user.find({
$and: [
{ age: { $gte: 18 } },
{ age: { $lte: 19 } },
{ parents: { $in: ["aP1", "cP1"] } },
{ name: { $ne: "b" } }
]
})
复制代码
嵌套查询
查询 description 中 score 大于等于 69 的数据:
db.user.find({ "description.score": { $gte: 69 } })
复制代码
$elemMatch 操作符
匹配包含 数组字段 的文档,其中至少有一个元素与所有指定的查询条件匹配
查询 description 中 skill 中 包含 “jump” 的数据:
db.user.find({ "description.skill": { $elemMatch: { $eq: "jump" } } })
复制代码
因为这里 skill 字段是一个字符串数组,也可以使用 $in
操作符,更简单
db.user.find({ "description.skill": { $in: ["jump"] } })
复制代码
如果 skill 字段是一个对象数组,需要对对象里面的某个字段在做筛选的话就需要得用 $elemMatch
操作符了,如:
description.skill = [
{key:"skillA",value:"sing"},
{key:"skillB",value:"jump"},
{key:"skillC",value:"rap"},
{key:"skillD",value:"basketball"},
]
description.skill = [
{key:"skillA",value:"sing"},
{key:"skillB",value:"jump"},
]
复制代码
db.user.find({ "description.skill": { $elemMatch: { value: "jump" } } })
复制代码
$where操作符查询
{ $where: <string|JavaScript Code> }
,$where
运算符将包含 JavaScript 表达式的字符串或完整的 JavaScript 函数传递给查询系统,可以使用this
或引用 JavaScript 表达式来操作当前文档。
查询 age = 18 且 description属性中的 score = 88 的数据:
db.user.find({
$where: function() {
return (this.age === 18 && this.description.score === 88)
}
})
复制代码
排序、分页
sort({<field>:1 或 -1})
1 为升序,-1 为降序limit(<number>)
设定结果集中显示的文档数,等于0时表示所有skip(<number>)
设定结果集中要跳过的文档数
现在共有5条数据,假设分页后每页只有一条数据,查询按照 age 倒叙排序的第3页的数据:
db.user.find().sort({ age: -1 }).skip(2 * 1).limit(1)
复制代码