mongodb
概念
mongoDB是一个nosql,也就是非关系型数据库,其使用一种类似JSON的BSON结构来记录数据,相较于mysql这种关系型数据库的库-表-行结构,mongoDB对应采用的是库-collection-document,文档没有固定的格式,但是一般放在同一个集合里的文档格式会比较统一
部署
win:
安装后在data创建db和log两个文件夹
在log创建mongo.log
将bin加到环境变量里
mongod --dbpath 刚创建的db路径
访问http://127.0.0.1:27017/查看是否启动成功
开机自启命令示例
mongod --dbpath "E:\MongoDB\data\db" --logpath "E:\MongoDB\data\log\mongo.log" -install -serviceName "MongoDB"
操作
基础
登录
mongo --port 27017 如果这个不行,用mongosh,如果都不行,先去下载mongoshell再mongosh
如果是远程连接
mongo "mongodb://mongodb0.example.com:28015"
mongo --host mongodb0.example.com:28015
mongo --host mongodb0.example.com --port 28015
使用某个集合(数据库),如果该集合不存在,则会被创建,需要注意的是,集合只有在被写入文档后才会真实存在,admin,local,config为保留数据库
use collectionname
db.myNewCollection1.insertOne( { x: 1 } ) #向collectionname库中myNewCollection1集合插入文档,如果库和集合不存在,则创建
查看库
show dbs
关闭服务
db.shutdownServer()
查看当前所在库
db
删库
db.dropDatabase()
数据类型
String − 这是存储数据最常用的数据类型。字符串在 MongoDB 必须是UTF-8有效。
Integer − 此类型用于存储数值。整数可以是32位 或 64位,具体取决于您的服务器。
Boolean −此类型用于存储布尔(true / false)值。
Double − 此类型用于存储浮点值。
Min/ Max keys −该类型用于将值与最低和最高的BSON元素进行比较。
Arrays −此类型用于将数组或列表或多个值存储到一个键中。
Timestamp− ctimestamp(时间戳)。当文档被修改或添加时,这可以方便地进行记录。
Object −此数据类型用于嵌入式文档。
Null −此类型用于存储 Null 值。
Symbol−此数据类型与字符串使用相同;但是,它通常是为使用特定符号类型的语言保留的。
Date − 此数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建 Date 对象并将日期,月份,年份递到其中来指定自己的日期时间。
Object ID −此数据类型用于存储文档的ID。
Binary data −此数据类型用于存储二进制数据。
Code −此数据类型用于将JavaScript代码存储到文档中。
Regular expression −此数据类型用于存储正则表达式。
crud
集合
创建集合
db.createCollection("name")
查看集合
show tables/collections
删除集合
db.collection.drop()
文档
增
插入文档(如果集合不存在,则会创建)
db.collection.insert() 如果_id不存在,创建,如果已存在,报错
即将被insertOne()\insertMany()代替!
db.collection.insert(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
document:要写入的文档。
writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
ordered:指定是否按顺序写入,默认 true,按顺序写入。
将创建的文档结构如下
字段名称 | 字段含义 | 类型 | 备注 |
---|---|---|---|
_id | ID | objectid或string | 主键,不设置会自动创建 |
project | 项目名 | string | |
owner | 项目所有人 | string | |
ownerid | 项目所有人id | string | |
om | 运维 | arrays | |
omid | 运维人员id | arrays | |
editdate | 最后修改日期 | date | |
priority | 重要等级 | string | p0-p4 |
db.testcol.insert({
project:"cmdb",
owner:"foo",
ownerid:"000001",
om:["chiruno","test02"],
omid:["000009","000002"],
editdate:new Date(),
priority:"p0"
})
查
查找文档
db.col.find()
db.col.find({key:value})
testdb> db.testcol.find()
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo',
ownerid: '000001',
om: [ 'chiruno', 'test02' ],
omid: [ '000009', '000002' ],
editdate: ISODate("2023-05-10T07:15:36.942Z"),
priority: 'p0'
}
]
testdb> db.testcol.find({project:"cmdb"})
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo',
ownerid: '000001',
om: [ 'chiruno', 'test02' ],
omid: [ '000009', '000002' ],
editdate: ISODate("2023-05-10T07:15:36.942Z"),
priority: 'p0'
}
]
查询文档,但是只显示部分字段
例
查询所有,但只显示project,owner,_id三个字段
testdb> db.testcol.find({},{project:1,owner:1})
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo'
}
]
查询所有,但是只显示project,owner两个字段
testdb> db.testcol.find({},{project:1,owner:1,_id:0})
[ { project: 'cmdb', owner: 'foo' } ]
改
更新文档
update
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
示例:
现有的文档:
testdb> db.testcol.find()
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo',
ownerid: '000001',
om: [ 'chiruno', 'test02' ],
omid: [ '000009', '000002' ],
editdate: ISODate("2023-05-10T07:15:36.942Z"),
priority: 'p0'
},
{
_id: ObjectId("645b5bcc118a3c99d6a3ffe1"),
project: 'prometheus',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T08:54:36.328Z"),
priority: 'p1'
}
]
现修改prometheus的om和omid,部分修改使用$set,不然会覆盖原文档,默认只修改匹配到的第一个文档,如需贪婪,使用{multi:true}
testdb> db.testcol.update({project:"prometheus"},{$set:{om:['chiruno','reisen'],omid:['000009','000004']}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
testdb> db.testcol.find({project:'prometheus'})
[
{
_id: ObjectId("645b5bcc118a3c99d6a3ffe1"),
project: 'prometheus',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno', 'reisen' ],
omid: [ '000009', '000004' ],
editdate: ISODate("2023-05-10T08:54:36.328Z"),
priority: 'p1'
}
]
整数增减
假设现有文档如下
db.products.insertOne(
{
_id: 1,
sku: "abc123",
quantity: 10,
metrics: { orders: 2, ratings: 3.5 }
}
)
现在相对其中orders,quality做整数加减法
db.products.updateOne(
{ sku: "abc123" },
{ $inc: { quantity: -2, "metrics.orders": 1 } }
)
删
删除文档
delectOne,delectMany,remove(将被取消)
testdb> db.testcol.remove({project:'prometheus'})
DeprecationWarning: Collection.remove() is deprecated. Use deleteOne, deleteMany, findOneAndDelete, or bulkWrite.
{ acknowledged: true, deletedCount: 1 }
如删除集合下全部文档:
db.inventory.deleteMany({})
删除 status 等于 A 的全部文档:
db.inventory.deleteMany({ status : "A" })
删除 status 等于 D 的一个文档:
db.inventory.deleteOne( { status: "D" } )
统计与高级查询
翻页
统计所有的记录数
countDocuments or estimatedDocumentCount
testdb> db.testcol.countDocuments()
2
限制返回的条数(分页)
db.COLLECTION_NAME.find().limit(n)
跳过前n条满足条件的查询结果
db.comment.find().skip(n)
合起来的使用效果(翻页)
//第一页
testdb> db.testcol.find().limit(2).skip(0)
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo',
ownerid: '000001',
om: [ 'chiruno', 'test02' ],
omid: [ '000009', '000002' ],
editdate: ISODate("2023-05-10T07:15:36.942Z"),
priority: 'p0'
},
{
_id: ObjectId("645b6621118a3c99d6a3ffe2"),
project: 'prometheus',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:38:41.712Z"),
priority: 'p1'
}
]
//第二页
testdb> db.testcol.find().limit(2).skip(1)
[
{
_id: ObjectId("645b6621118a3c99d6a3ffe2"),
project: 'prometheus',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:38:41.712Z"),
priority: 'p1'
},
{
_id: ObjectId("645b6904118a3c99d6a3ffe3"),
project: 'thanos',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:51:00.119Z"),
priority: 'p2'
}
]
排序
排序查询
可以指定字段排序,1为升序-1为降序,可以组合多个字段使用
db.col.find().sort({key:1/-1,key2:1/-1})
testdb> db.testcol.find().sort({ownerid:-1})
[
{
_id: ObjectId("645b6929118a3c99d6a3ffe4"),
project: 'grafana',
owner: 'reisen',
ownerid: '000004',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:51:37.737Z"),
priority: 'p3'
},
{
_id: ObjectId("645b6621118a3c99d6a3ffe2"),
project: 'prometheus',
owner: 'eda',
ownerid: '000003',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:38:41.712Z"),
priority: 'p1'
},
...
正则
正则
find({key:/parten/})
testdb> db.testcol.find({owner:/^rei/})
[
{
_id: ObjectId("645b6929118a3c99d6a3ffe4"),
project: 'grafana',
owner: 'reisen',
ownerid: '000004',
om: [ 'chiruno' ],
omid: [ '000009' ],
editdate: ISODate("2023-05-10T09:51:37.737Z"),
priority: 'p3'
}
]
值比较
值比较
写法跟shell差不多
$lt | 小于 |
---|---|
$lte | 小于等于 |
$gt | 大于 |
$gte | 大于等于 |
$ne | 等于 |
find({key:{$lt:value}}) 查找大于某值的文档
包含
包含查询
find(key:{$in:["abc","edf"]}) 查找包含有abc和edf的
testdb> db.testcol.find({om:{$in:['sanae']}})
[
{
_id: ObjectId("645b6904118a3c99d6a3ffe3"),
project: 'thanos',
owner: 'eda',
ownerid: '000003',
om: [ 'sanae' ],
omid: [ '000008' ],
editdate: ISODate("2023-05-10T09:51:00.119Z"),
priority: 'p2'
}
]
多条件
条件连接查询
find({$and/$or:[{条件a},{条件b},{},{}...]})
testdb> db.testcol.find({$and:[{om:{$in:['chiruno']}},{priority:'p0'}]})
[
{
_id: ObjectId("645b4498118a3c99d6a3ffe0"),
project: 'cmdb',
owner: 'foo',
ownerid: '000001',
om: [ 'chiruno', 'test02' ],
omid: [ '000009', '000002' ],
editdate: ISODate("2023-05-10T07:15:36.942Z"),
priority: 'p0'
}
]
类型
按照值的类型来搜索
db.testcol.find({project:{$type:"string"}})
聚合、管道符
//等同于select by_user, count(*) from testcol group by owner
testdb> db.testcol.aggregate([{$group : {_id : "$owner", num_tutorial : {$sum : 1}}}])
[
{ _id: 'foo', num_tutorial: 1 },
{ _id: 'eda', num_tutorial: 2 },
{ _id: 'reisen', num_tutorial: 1 }
]
其他聚合运算符
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 将值加入一个数组中,不会判断是否有重复的值。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
其他管道符
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。
索引
mongodb除了支持基于单字段(单字段索引)或多字段(复合索引)的排序索引,还支持空间地理索引、文本索引、哈希索引
默认情况下,mongodb会以_id为默认主键
地理空间索引(Geospatial Index)
为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。
文本索引(Text Indexes)
MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”),而将集合中的词作为词干,只存储根词。
哈希索引(Hashed Indexes)
为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询
当查询的key只包含索引的时候,mongo会直接从索引返回结果,而不会把文档带入内存,大大提高了效率
查看集合索引
db.col.getIndexes
testdb> db.testcol.getIndexes()
[ { v: 2, key: { _id: 1 }, name: '_id_' } ]
创建索引
db.collection.createIndex(keys, options)
参数
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
---|---|---|
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
testdb> db.testcol.createIndex({project:1})
project_1
testdb> db.testcol.getIndexes()
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { project: 1 }, name: 'project_1' }
]
删除索引
dropIndex({key:n}) 删除单个索引
dropIndexes() 删除所有索引
testdb> db.testcol.dropIndex({project:1})
{ nIndexesWas: 2, ok: 1 }
testdb> db.testcol.getIndexes()
[ { v: 2, key: { _id: 1 }, name: '_id_' } ]
解析一条查询语句的索引执行状况
db.col.find().explain()
建立索引前
testdb> db.testcol.find({project:'cmdb'}).explain()
{
explainVersion: '1',
queryPlanner: {
namespace: 'testdb.testcol',
indexFilterSet: false,
parsedQuery: { project: { '$eq': 'cmdb' } },
queryHash: '47226C69',
planCacheKey: '47226C69',
maxIndexedOrSolutionsReached: false,
maxIndexedAndSolutionsReached: false,
maxScansToExplodeReached: false,
winningPlan: {
stage: 'COLLSCAN', //注意这里,COLLSCAN表示全集合扫描
filter: { project: { '$eq': 'cmdb' } },
direction: 'forward'
},
rejectedPlans: []
},
command: { find: 'testcol', filter: { project: 'cmdb' }, '$db': 'testdb' },
serverInfo: {
host: 'wg8hf6ct4owq5mi',
port: 27017,
version: '6.0.5',
gitVersion: 'c9a99c120371d4d4c52cbb15dac34a36ce8d3b1d'
},
serverParameters: {
internalQueryFacetBufferSizeBytes: 104857600,
internalQueryFacetMaxOutputDocSizeBytes: 104857600,
internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,
internalDocumentSourceGroupMaxMemoryBytes: 104857600,
internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,
internalQueryProhibitBlockingMergeOnMongoS: 0,
internalQueryMaxAddToSetBytes: 104857600,
internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600
},
ok: 1
}
建立索引后
testdb> db.testcol.createIndex({project:1})
project_1
testdb> db.testcol.find({project:'cmdb'}).explain()
{
explainVersion: '1',
queryPlanner: {
namespace: 'testdb.testcol',
indexFilterSet: false,
parsedQuery: { project: { '$eq': 'cmdb' } },
queryHash: '47226C69',
planCacheKey: 'B8C89C45',
maxIndexedOrSolutionsReached: false,
maxIndexedAndSolutionsReached: false,
maxScansToExplodeReached: false,
winningPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN', //IXSCAN表示走了索引
keyPattern: { project: 1 },
indexName: 'project_1',
isMultiKey: false,
multiKeyPaths: { project: [] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: { project: [ '["cmdb", "cmdb"]' ] }
}
},
rejectedPlans: []
},
command: { find: 'testcol', filter: { project: 'cmdb' }, '$db': 'testdb' },
serverInfo: {
host: 'wg8hf6ct4owq5mi',
port: 27017,
version: '6.0.5',
gitVersion: 'c9a99c120371d4d4c52cbb15dac34a36ce8d3b1d'
},
serverParameters: {
internalQueryFacetBufferSizeBytes: 104857600,
internalQueryFacetMaxOutputDocSizeBytes: 104857600,
internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,
internalDocumentSourceGroupMaxMemoryBytes: 104857600,
internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,
internalQueryProhibitBlockingMergeOnMongoS: 0,
internalQueryMaxAddToSetBytes: 104857600,
internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600
},
ok: 1
}
现设计cmdb的数据结构
project集合
projectid 项目id,全局唯一,必填(计划由程序生成,无需由用户手动输入)
projectname 项目名,全局唯一,必填
owner 项目拥有者,只能从user集合中存在的人中选择,项目拥有者只能有一个人,必填字段
owerid 项目拥有者的id,根据owner在user集合中的userid走
dev 开发人员,数组,同样只能从user中选
devid 开发人员id,数组,和ownerid一样和dev对应
department 项目所属部门,必须存在于department集合中
ipgroup 项目所拥有的服务器的IP,数组,ip必须存在于server集合中
platform_label 机器所属平台,必须存在于platform集合中
label 数组,自定义标签,其值的格式如"app:thanos"
priority 项目重要等级,从p0-p4这五个等级中选择
edit_time 最后修改时间
create_time 创建时间
计划可以通过项目名、部门、拥有人、ip来搜索
服务器集合
ip_outer 公网
ip_inner 内网
project 所属项目
os 操作系统
ansible_statu 连通性测试
create_time 上架时间
edit_time 最后的修改时间
user集合
username 用户名,必填项,全局唯一
userid 用户id,必填项,全局唯一(计划由程序生成,不需要用户手动输入)
email 邮箱
phone 手机号
评论已关闭