Mongo

MongoDB

启动

mongod启动最少要三个参数
--port 默认27017
--dbpath 默认/data/db
--logpath 默认输出在stdout
启动后用mongo连接服务端 mongo --port=27017, --port是默认参数,可以省略

基本概念

MongoDB是有 Database Collections Documents 结构组成,分别代表 库 表 键值对

Database

  • 对于Database 使用use Database 切换到对应的库中,如果该库不存在,会在这个库存储数据的时候自行创建,所以我们可以直接切换到一个不存在的库中,一个库是对应一个dbpath的
    cls mongo清屏

    show dbs 等同于show databases
    use databases 使用库
    db 查看当前所在库
    db.dropDatebase() 删除当前库 这里的db就是指当前库

  • 默认自带三个库
    admin root数据库,如果将一个用户添加到这个库,自动继承所有权限
    local 这个数据永远不会被复制,用来存储于本地单台服务器的任意集合,这里的复制主要指主从复制机制
    config 用于分片设置,在数据库内部使用,用来保存分片的相关信息

Collections

  • 对于Collections ,我们在use Database切换后 试着给该表创建条数据 db.fruit.insert({name:"apple"}) 这时候因为存储了新的数据,会自动创建不存在的Database 和 collection
    db.fruit.drop() 删除表

  • 查看所有集合
    show collections | show tables

  • 创建集合
    db.createCollection(集合名,[options])
    options可以是如下参数
    capped 布尔值 如果为真 创建固定大小集合,达到最大值后悔自动覆盖最早的文档,一般和size,max搭配使用
    size 数值 为固定集合指定一个最大值,也就是字节数
    max 数值 指定固定集合中包含文档的最大数量
    db.createCollection("test",{max:100,capped:True,size:50000}) 当集合字节数达到50000或者文档数达到100 就会进行自动覆盖

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

基本操作

insert 插入操作 如果不指定_id字段,会自动生成,如果指定了_id就用指定的字段

格式语法1  db.fruit.insertOne({name:"apple"}) 
新版本的语法insert支持单条也支持多条插入
格式语法2  db.fruit.insertMany([{name:"apple"},{name:"pear"},{name:"banana"}])

insertMany(
	[{document1},{document2},{document3}],
	{writeConcern: 1,//写入策略,默认1,要求确认写操作, 0 是不要求,
	ordered: true, //指定是否按顺序写入默认是真,按顺序写入,
	}
)

还可以用js的for循环进行插入
```
> for (i=0;i<10;i++){
... db.test.insert({name:"aa"+i,index:i})
... }
WriteResult({ "nInserted" : 1 })   #因为是循环 每次插入只有一条,因此显示插入条数始终是1条
```

find 查询操作

db.fruit.find({""})
db.test.find({age:18}) 单条件查询
db.test.find({age:18,city:"shanghai"}) 多条件查询语法1
db.test.find({$and:[{age:18},{city:"shanghai"}]}) 多条件查询语法2
db.test.find({$and:[{age:18},{age:19}]}) 这种多条件要注意,同样的文档字段在多条件查询中,后面的会覆盖前面的
db.test.find({$or:[{age:18},{city:"shanghai"}]}) 多条件查询语法2 或条件
db.test.find({"age":{$lt:50}}) 等同于where age < 50
db.test.find({"age":{$lte:50}}) 等同于where age <= 50
db.test.find({"age":{$ne:50}}) 等同于where age != 50
db.test.find({"age":{$gt:50},$or:[{name:"大娃"},{name:"二娃"}]}) 匹配age大于50,并且name是大娃或者二娃的结果
对于子文档的查询 db.test.insertOne({name:"apple",from:{country:"usa",province:"los angle"}}) 比如插入一条嵌套的子文档,那么查询方式是db.test.find({"from.country":"usa"})

模糊匹配只能用正则实现
db.test.find({"city":/^shan/,name:"大娃"}) //按正则语法查询 /^shan/ shan开头的 /我/ 匹配带有"我"的文档

分页 将返回值按照每页n条数据显示,这里需要skip()和limit() skip是显示第N页 索引默认从0开始,limit限制每页显示的个数
db.test.find({name:/^aa/}).sort({index:-1}).skip(1).limit(4) 显示第二页4个数据
排序
db.test.find({name:/^aa/}).sort({index:-1}) 对返回值按照index进行排序 -1是降序 1 是升序
db.test.find({name:/^aa/}).sort({index:-1,name:1}) index降序 同时name升序排列

汇总数count()
db.集合.count() 或者 db.集合.find().count()

去重distinct()
db.集合.find("字段").distinct()

对数组的查询

db.test.insert([{name:"apple",color:["red","yellow"]},{name:"mongo",color:["blue","black"]},])

db.test.find({color:"red"})和db.test.find({$or:[{color:"red"},{color:"blue"}]})会产生不同的结果,
前者返回color含有red的记录,只会返回一条数据,而后者返回的是color含有red或者blue的记录,2条都会返回
---------------------------------------------------------------------------------------------
比如插入的数据为
db.test.insertOne({
title:"title1",
location:[{"city":"los angles","state":"ca","country":"usa"},
{"city":"ningbo","state":"zhejiang","country":"china"},
{"city":"rome","state":"lazio","country":"italy"},
]
})
我们对location的元素要多个匹配的时候可以用
db.test.find({"location.city":"ningbo","location.city":"rome"})
或者用$elemMatch参数  这2中都是对子对象中满足多个字段条件时候使用
db.test.find({"location":{$elemMatch:{"country":"china","city":"ningbo"}}})
他们的返回值会是如下
{ "_id" : ObjectId("62a750fa76a416fb3c2c4bc1"), "title" : "title1", "location" : [ { "city" : "los angles", "state" : "ca", "country" : "usa" }, { "city" : "ningbo", "state" : "zhejiang", "country" : "china" }, { "city" : "rome", "state" : "lazio", "country" : "italy" } ] }

按照数组的长度查询 用$size拼接符 比如对下面插入的内容查找color数组为2个的  db.test.find({color:{$size:2}})
db.test.insert([{name:"apple",color:["red","yellow"]},{name:"mongo",color:["blue","black"]},])

投影机制,我们对返回值的字段也可以设置是否需要,拿上面的例子db.test.find({"location":{$elemMatch:{"country":"china","city":"ningbo"}}})
我们改成db.test.find({ "location":{$elemMatch:{"country":"china","city":"ningbo"}} },{"_id":0,"location":1}) 他就只返回location字段,_id因为设置为0不会返回,titile没有提及,也不会返回

remove命令 删除文档

语法:

db.集合.remove(
query,     删除条件
{
justOne: boolean   为真只删除一个文档
writeConcern: document  抛出异常的级别
}
)
示例
db.test.remove({aa:"aa"},{justOne:"True"})  所有匹配的记录只会删除一条

db.test.remove({a:1}) 删除a为1的记录
db.test.remove({a:{$lt:5}}) 删除a小于5的记录
db.test.remove({}) 删除所有记录
db.test.remove({_id:ObjectId("62a82a137e7718372c570cfc")}) 对于自动生成的_id 要把objectid函数写上,但是如果是自己手动创建的_id字段就不用

update命令 更新文档

语法

db.集合.update(
query, 	查询条件
update,	更新的对象
{
upsert:boolean,	如果为真,不存在是则插入,默认为真
multi:boolean	默认false只更新第一条记录,true则更新全部记录
writeConcern:document  抛出异常的级别
}
)

update 默认会将找到的记录删除,然后插入一条新的.假如有条记录为{age:15},{name:"aaa"},我们db.test.update({age:15},{age:28}) 这条记录的name:aaa也会消失不见.
要是只想更新某个字段,其他字段保持不变,需要下面的$set 拼接符

db.test.updateOne({name:"apple"},{$set:{from:"china"}}) 比如这条会找到name为apple的记录,新增一个键from,如果from这个键没有,则新增后面的值,如果有则更新后面的值
updateOne 无论匹配到多少条记录,永远只更新第一条; updateMany 匹配多少条就更新多少条
updateOne / updateMany 更新条件部分必须要有如下参数

  • $set/$unset
  • $push/$pushAll/$pop
  • $pull/$pullAll
  • $addToSet

drop 删除集合(表)

db.集合.drop() 表会被删除,全部文档和索引都会被删除
db.dropDatabase() 这个语句在use database语句后执行,删除的就是当前的库

  • 逻辑符



$type的应用

$type代表了各种数据类型的连接符,可以用$type查特定的文档类型.

类型 数字 备注
Double 1
String 2
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
db.test.find({age:{$type:2}}) 或者 db.test.find({age:{$type:"String"}}) 查所有age字段 值是字符串类型的结果 在数据库中所有的数字默认都是double类型

索引

创建索引

  • Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可

db.collection.createIndex(keys, options) db.col.createIndex({"title":1}

createIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)

db.col.createIndex({"title":1,"description":-1}) 会以title字段升序创建索引,如果titile字段相同时以description字段降序创建索引 代码示例

db.test.createIndex({"name":1},{name:"index_name",expireAfterSeconds:10})

  • options可选参数详情如下
Parameter Type Description
background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false
unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups Boolean 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparse Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. 有些字段为空值,对这些空值的字段不创建索引
expireAfterSeconds integer 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
v index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weights document 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_language string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_override string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

查看集合索引

db.col.getIndexes()

查看集合索引大小

db.col.totalIndexSize()

索引删除

db.col.dropIndexes() 删除集合指定索引

db.col.dropIndex("索引名称") 删除指定索引

复合索引

一个索引由多个key进行维护的索引 称为复合索引 db.test.createIndex({name:1,age:-1})

关系型数据库的复合索引采取的是左包含原则, 比如id是自增索引,后续增加了name age字段作为复合索引.

那么查询的时候id name age 或者id name 或者id age 这样的查询方式是可以有效利用索引机制,提高查询速度的.但是如果查询顺序为age name id的话 就利用不了索引机制了

mongodb 和关系型数据库也差不多,只是有点不同,只要符合左包含原则的前提下,顺序调换一下也可以,mongo内部会根据字段顺序自动调整.所以mongdb只要查询字段有id字段

官方文档 https://www.mongodb.com/docs/v5.0/core/multikey-index-bounds/

聚合查询

Mongo自带的聚合参数


常见步骤的运算符

$match
$eq / $gt / $gte / $tt / $lte  $andl $orl $not / $in  $geowithin / $intersect 
$project 
1. 选择需要的或排除不需要的字段  
2. $map / $reduce / $fiter  $range  $muttiply / $divide / $substract / $add  
3. $year / $month / $dayofMonth / $hour / $minute / $second等等

$group
$sum / $avg
$push / $addToset 
$ first / $last / $max / $min

$unwind  用来展开数组
$graphLookup  图搜索
$facet/$bucket  分面搜索

aggregate() 方法

语法: db.集合.aggregate(AGGREGATE_OPERATION)

以一个$sum求和为例,插入的文档如下

db.test2.insert([
    {
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
    },
    {
       title: 'NoSQL Overview', 
       description: 'No sql database is very fast',
       by_user: 'runoob.com',
       url: 'http://www.runoob.com',
       tags: ['mongodb', 'database', 'NoSQL'],
       likes: 10
    },
    {
       title: 'Neo4j Overview', 
       description: 'Neo4j is no sql database',
       by_user: 'Neo4j',
       url: 'http://www.neo4j.com',
       tags: ['neo4j', 'database', 'NoSQL'],
       likes: 750
    }
])

求和的语法为 db.test2.aggregate([{$group:{_id:"$by_user",sum_by_user:{$sum:"$likes"}}}])

对语法详解

db.test2.aggregate(
#聚合函数后要一个数组类型
	[
		# $group 后面{_id:"$by_user"} 表示以by_user字段进行分组, _id和文档里的_id不是一个事,不要搞混
		# sum_by_user 是一个自定义的字段,用来展示聚合分组后的字段
		# {$sum:"$likes"} 代表对likes字段进行求和
		{$group:{_id:"$by_user",sum_by_user:{$sum:"$likes"}}}
	]
)
常见表达式 描述 实例
$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"}}}])

搭建副本集

https://www.cnblogs.com/boshen-hzb/p/10419760.html

  • 创建数据目录

    mkdir -p /repl/data1
    mkdir -p /repl/data2
    mkdir -p /repl/data3
    
  • 搭建副本集

    mongod --prot 27017 --dbpath /repl/data1 --bind_ip 0.0.0.0 --replset myreplace/localhost:27018,localhost:27019
    
    mongod --prot 27018 --dbpath /repl/data2 --bind_ip 0.0.0.0 --replset myreplace/localhost:27017,localhost:27019
    
    mongod --prot 27019 --dbpath /repl/data3 --bind_ip 0.0.0.0 --replset myreplace/localhost:27018,localhost:27017
    

    --replset 副本集 myreplace是副本集的自定义名称 后面是副本集其他节点的主机ip和端口

  • 配置副本集,连接任意节点 这里进入mongo界面设置

    1. use admin

    2. 初始化副本集

      var config = {
          _id:"myreplace",
          members:[
              {_id:0,host:"localhost:27017"},
              {_id:1,host:"localhost:27018"},
              {_id:2,host:"localhost:27019"},
          ]
      }
      
    3. 初始化配置

      rs.initiate(config)

    4. 设置客户端临时访问

      rs.slaveok()

posted @ 2022-06-14 15:37  零哭谷  阅读(444)  评论(0编辑  收藏  举报