
目录
- 1. docker安装mongoDB
- 2. 库-database
-
3. 集合-collection
- 3.1 命名规范
- 3.2 增-createCollection
- 3.3 删-drop
-
4. 文档-document
- 4.1 命名规范
-
4.2 增-insert,insertMany(单个增,批量增)
- 4.2.1 insertOne-单个增
- 4.2.2 insertMany-批量增
- 4.2.3 insert-单个增或批量增
-
4.3 查-find
- 4.3.1 find-查所有,条件查,投影查
- 4.3.2 limit,offset翻页查,排序
- 4.3.3 正则模糊查询(相当于like
- 4.3.4 大于gt,小于lt,大于等于gte,小于等于lte,不等于ne
- 4.3.5 包含查询-\(in,不包含查询-\nin
- 4.3.6 条件连接-\(and,\or
- 5.1 mongo B-tree与mysql B+tree分析
- 5.2.1 单字段索引
- 5.2.2 复合索引
- 5.2.3 其他索引-地理空间索引,文本索引,哈希索引
- 6.1 初始化
1. docker安装mongoDB
docker pull mongo:5.0
docker run -itd --name mongo:5.0 -p 27017:27017 mongo --auth
-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。
--auth:需要密码才能访问容器服务。
$ docker exec -it mongo mongo admin
# 创建一个名为 admin,密码为 123456 的用户。
> db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]};
# 尝试使用上面创建的用户信息进行连接。
> db.auth('admin', '123456'
2. 库-database
use 数据库名称 //选择和创建数据库的语法格式
注意:在MongoDB中,集台只有在内容插入后才会创建!就是说,创建集合(数据表后,必须要再插入一个文档(记录,集合才会真正的创建
db //查看当前正在使用的数据库名称
db.user.getDB( //获取库名
db.version( //获取版本
3. 集合-collection
集合,类似关系型数据库中的表。
可以显示的创建,也可以隐式的创建。
3.1 命名规范
1.集合名不能是空字符串""。
2.集合名不能含有\0字符(空字符,这个字符表示集合名的结尾。
3.集合名不能以"system."开头,这是为系统集合保留的前缀。
4.用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除 非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
3.2 增-createCollection
增:
集合创建(显示创建:
db.createCollection("test2"
集合创建(隐士创建:
当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合
注:通常我们使用隐式创建文档即可。
3.3 删-drop
删:
db.集合名.drop(
db.test2.drop(
注:如果成功删除选定集合,则 drop( 方法返回 true,否则返回 false
4. 文档-document
文档(document)的数据结构和 JSON 基本一样。
4.1 命名规范
1键不能含有\0 (空字符。这个字符用来表示键的结尾。
2"."点和$有特别的意义,只有在特定环境下才能使用。
3)以下划线"_"开头的键是保留的(不是严格要求的。
4.2 增-insert,insertMany(单个增,批量增)
注:
1.user代表集合名称
2.comment集合如果不存在,则会隐式创建
3.mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字,否则取出来就有问题了。
4.插入当前日期使用 new Date(
5.插入的数据没有指定 _id,会自动生成主键值
6.如果某字段没值,可以赋值为null,或不写该字段。
7.批量插入如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。所以需要处理异常
4.2.1 insertOne-单个增
单个增:
db.user.insertOne([{
"name":"jeff004",
"age":18,
}]
4.2.2 insertMany-批量增
批量增:
db.user.insertMany([
{"name":"ooo","sex":"男"},
{"name":"xxx","sex":"女"}
]
结果:acknowledged:true insertedlds:(Array 2 Elements
4.2.3 insert-单个增或批量增
//批量增
db.user.insert([{
"name":"jeff006",
"age":18,
},
{
"name":"jeff007",
"age":18,
}
]
//单个增
db.user.insert({
"name":"jeff008",
"age":18,
}
4.3 查-find
4.3.1 find-查所有,条件查,投影查
db.user.find( //查询集合所有
db.user.find({name:"123"}; //条件查询
db.user.findOne({name:"123"}; //条件查询,返回符合条件的第一条数据
db.user.find({_id:ObjectId("643622e64a2ad86c86062273"}; //_id查询
//投影查
//如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。
//投影查,1:显示 0:不显示,默认 _id 会显示。
db.user.find({name:"123"},{"name":1};
db.user.find({name:"123"},{name:1,_id:0}; //_id不显示
4.3.2 limit,offset翻页查,排序
//limit限制条数,skip跳过条数
db.user.find(.limit(10.skip(2
//排序
db.user.find(.sort({age:-1} //-1降序,1升序
db.user.find(.sort({age:-1,userid:1} //先按age降序,再按userid生序排列
//排序取第一条
db.user.find(.sort({age:-1}.limit(1//max,先排序,再取第一条
db.user.find(.sort({age:1}.limit(1 //min,先排序,再取第一条
4.3.3 正则模糊查询(相当于like
db.user.find({name:/正则表达式/}
db.user.find({name:/ef/} //匹配jeff
4.3.4 大于gt,小于lt,大于等于gte,小于等于lte,不等于ne
//大于$gt,小于$lt,大于等于$gte,小于等于$lte,不等于$ne
//不等于
db.user.find({name:{$ne:"jeff"}} //name!=“jeff”的所有
//大于
db.user.find({age:{$gt:5}} //age大于5的所有
//小于
db.user.find({age:{$lt:100}} //age小于100的所有
4.3.5 包含查询-\(in,不包含查询-\nin
db.user.find({name:{$in:["jeff","chery"]}} //user集合中name字段包含的
db.user.find({name:{$nin:["jeff","chery"]}} ////user集合中name字段不包含的
4.3.6 条件连接-\(and,\or
db.user.find($and:[ { },{ },{ }]
//name=jeff and age=10
db.user.find({$and:[{name:"jeff"},{age:10}]} //and
//name正则匹配 and age>5
db.user.find({$and:[{name:/ef/},{age:{$gt:5}}]} //and
//name="jeff" or age>10
db.user.find({$or:[{name:"jeff"},{age:{$gt:10}}]} //or
4.4 改-update,updateOne
//默认只修改第一条 $set
db.user.update({name:"123"},{$set:{name:"jeff"}}
//修改符合条件的所有数据 multi:true
db.user.update({name:"123"},{$set:{name:"jeff"}},{multi:true}
//每次原基础上递增10 $inc
db.user.update({name:"jeff"},{$inc:{age:10}}
//$max,$min使用
//解释:age大于小于300则修改,否则不修改
db.user.updateOne({name:"jeff"},{$max:{age:300}}
db.user.updateOne({name:"jeff"},{$min:{age:300}}
4.5 删-remove
//删除符合条件所有
db.user.remove({name:"jeff"}
4.6 统计aggregate聚合函数-count,max,min,avg,sum
//count
db.user.count( //集合全部计数
db.user.count({name:"jeff"} //集合条件计数
//avg
db.user.aggregate([
{ $group : { _id : null, avgAge: { $avg : "$age" } } }
]
//max
db.user.aggregate([
{ $group : { _id : null, avgAge: { $max : "$age" } } }
]
//min
db.user.aggregate([
{ $group : { _id : null, avgAge: { $max : "$age" } } }
]
//sum
db.user.aggregate([
{ $group : { _id : null, avgAge: { $max : "$age" } } }
]
5. 索引-index
5.1 mongo B-tree与mysql B+tree分析
mongo索引结构:B-Tree
mysql索引结构:B+Tree
B-Tree与B+Tree区别:B+tree只有叶子结点存数据,B-Tree所有节点都存数据
原因:mongo与mysql使用场景不一样,mysql是关系型,mongo是非关系性
至于为什么MongoDB使用B树而不是B +树,可以从其设计的角度考虑它。 MongoDB不是传统的关系数据库,而是以BSON格式(可以认为是JSON存储的nosql。目的是高性能,高可用性和易于扩展。
Mysql是关系型数据库,最常用的是数据遍历操作(join,而MongoDB它的数据更多的是聚合过的数据,不像Mysql那样表之间的关系那么强烈,因此MongoDB更多的是单个查询。
由于Mysql使用B+树,数据在叶节点上,叶子节点之间又通过双向链表连接,更加有利于数据遍历,而MongoDB使用B树,所有节点都有一个数据字段。只要找到指定的索引,就可以对其进行访问。毫无疑问,单个查询MongoDB平均查询速度比Mysql快。
5.2 索引分类
5.2.1 单字段索引
MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。 对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引。
5.2.2 复合索引
复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后 在每个userid的值内,再在按score倒序排序。
5.2.3 其他索引-地理空间索引,文本索引,哈希索引
为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面 几何的二维球面索引。
5.3 索引查看
db.user.getIndexes( //查看索引
[
{
"v" : 2, # mongodb引擎的版本号(不用管
"key" : {
"_id" : 1 # 默认主键
},
"name" : "_id_", # 索引名称
"ns" : "jeff.comment" # 索引的位置
}
]
5.4 索引创建
db.集合名.createIndex(keys, options
//升序普通索引
db.user.createIndex({userid:1}
//1升序索引,-1降序索引
db.user.createIndex({name:1},{unique:true} //新,推荐
db.user.ensureIndex({name:1},{unique:true} //老,不推荐,3.0.0版本前,createIndex的别名
//复合索引
db.user.createIndex({userid:1,name:-1} //先userid升序,再name降序
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. |
提示:
注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(,之后的版本使用了 db.collection.createIndex( 方法,ensureIndex( 还能用,但只是 createIndex( 的别名。
5.5 索引删除
db.集合名.dropIndex(索引
//指定删除:删除{userid:1}索引
db.user.dropIndex({userid:1}
//全部删除:删除集合全部索引,除_id索引
db.user.dropIndexes(
5.6 explain执行计划
分析查询性能 通常使用执行计划来查看查询的情况,如查询耗费的时间、是 否基于索引查询等。
那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
db.集合名.find(query,options.explain(options
//eg:
db.user.find({"name":"jeff"}.explain(
6. golang使用mongoDB
6.1 初始化
import (
"context"
"encoding/json"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
var Client *mongo.Client
func initMongo(url string error {
clientOptions := options.Client(.ApplyURI(url
client, err := mongo.Connect(context.TODO(, clientOptions
if err != nil {
log.Fatal(err
}
// 检测连接
err = client.Ping(context.TODO(, nil
if err != nil {
fmt.Println("连接失败!err:", err
return err
}
fmt.Println("Connected to MongoDB!"
Client = client
return nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
}
6.2 findOne-查询单个
//查询单个
func findOne(detection_coll *mongo.Collection, filter bson.D (result map[string]interface{}, err error {
err = detection_coll.FindOne(context.TODO(, filter.Decode(&result
if err != nil {
fmt.Println(err
return nil, err
}
return
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
// 查询单条数据
type User struct {
Id string `json:"_id"`
Age int `json:"age"`
Name string `json:"name"`
}
user := User{}
//查询单个
filter := bson.D{{Key: "name", Value: "jeff"}}
data, err := findOne(detection_coll, filter
if err != nil {
fmt.Println(err
return
}
fmt.Println(data
bStr, _ := json.Marshal(data
_ = json.Unmarshal(bStr, &user
fmt.Println(user
}
6.3 find-查询所有
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
type User struct {
Id string `json:"_id"`
Age int `json:"age"`
Name string `json:"name"`
}
//查询所有
func find(detection_coll *mongo.Collection, filter bson.D, reslist []*User (reqlist []*User, err error {
cur, err := detection_coll.Find(context.TODO(, filter
if err != nil {
return nil, err
}
if err = cur.Err(; err != nil {
return nil, err
}
err = cur.All(context.Background(, &reslist
if err != nil {
return nil, err
}
_ = cur.Close(context.Background(
return reslist, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
userList := []*User{}
//查询所有
filter := bson.D{{Key: "age", Value: 18}}
list, err := find(detection_coll, filter, userList
if err != nil {
fmt.Println(err
return
}
fmt.Println(list
for _, one := range list {
fmt.Println(one
}
}
6.4 InsertOne-单条插入
//单条插入
func InsertOne(detection_coll *mongo.Collection, info interface{} (objectID interface{}, err error {
objId, err := detection_coll.InsertOne(context.TODO(, info
if err != nil {
return nil, err
}
fmt.Println("_id:", objId.InsertedID
return objId, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
userInfo := User{
Name: "jeff002",
Age: 20,
}
objectID, err := InsertOne(detection_coll, userInfo
if err != nil {
fmt.Println(err
return
}
fmt.Println(objectID
}
6.4 InsertMany-批量插入1
//批量插入
func InsertMany(detection_coll *mongo.Collection, infolist []interface{} (count int, err error {
objId, err := detection_coll.InsertMany(context.TODO(, infolist
if err != nil {
return 0, err
}
return len(objId.InsertedIDs, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
userInfo1 := User{
Name: "jeff001",
Age: 20,
}
userInfo2 := User{
Name: "jeff002",
Age: 20,
}
userList := []User{userInfo1, userInfo2}
list := []interface{}{}
bStr, _ := json.Marshal(userList
_ = json.Unmarshal(bStr, &list
count, err := InsertMany(detection_coll, list
if err != nil {
fmt.Println(err
return
}
fmt.Println(count
}
6.5 BulkWrite-批量插入2
//批量插入
func batchSave(detection_coll *mongo.Collection, models []mongo.WriteModel (insertedCount int64, err error {
opts := options.BulkWrite(.SetOrdered(false
res, err := detection_coll.BulkWrite(context.TODO(, models, opts
if err != nil {
return 0, err
}
return res.InsertedCount, nil
}
type User struct {
Age int `json:"age"`
Name string `json:"name"`
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
userInfo1 := User{
Name: "jeff003",
Age: 20,
}
userInfo2 := User{
Name: "jeff004",
Age: 20,
}
models := []mongo.WriteModel{
mongo.NewInsertOneModel(.SetDocument(userInfo1,
mongo.NewInsertOneModel(.SetDocument(userInfo2,
}
count, err := batchSave(detection_coll, models
if err != nil {
fmt.Println(err
return
}
fmt.Println(count
}
6.6 UpdateMany-批量更新
//批量更新
func updateMany(detection_coll *mongo.Collection, filter, updateData interface{} (matchedCount, modifiedCount int64, err error {
result, err := detection_coll.UpdateMany(context.TODO(, filter, updateData
if err != nil {
return 0, 0, err
}
//matchedCount匹配数
//modifiedCount修改数
return result.MatchedCount, result.ModifiedCount, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
detectionIds := []string{"jeff001", "jeff002"}
filter := bson.D{{Key: "name", Value: bson.D{{Key: "$in", Value: detectionIds}}}}
// filter := bson.D{{Key: "name", Value: "jeff001"}} //条件
update := bson.D{
{Key: "$set", Value: bson.D{
{Key: "age", Value: 89},
}},
}
matchedCount, modifiedCount, err := updateMany(detection_coll, filter, update
if err != nil {
fmt.Println(err
return
}
fmt.Println("匹配数:", matchedCount
fmt.Println("修改数:", modifiedCount
}
6.7 DeleteOne-删除一个
//删除一个
func deleteOne(detection_coll *mongo.Collection, filter interface{} (deletedCount int64, err error {
result, err := detection_coll.DeleteOne(context.TODO(, filter
if err != nil {
return 0, err
}
return result.DeletedCount, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
detectionIds := []string{"jeff001", "jeff002"}
filter := bson.D{{Key: "name", Value: bson.D{{Key: "$in", Value: detectionIds}}}}
deletedCount, err := deleteOne(detection_coll, filter
if err != nil {
fmt.Println(err
return
}
fmt.Println("删除数量:", deletedCount
}
6.8 DeleteMany-批量删除
//批量删除
func deleteOne(detection_coll *mongo.Collection, filter interface{} (deletedCount int64, err error {
result, err := detection_coll.DeleteMany(context.TODO(, filter
if err != nil {
return 0, err
}
return result.DeletedCount, nil
}
func main( {
url := "mongodb://admin:123456@127.0.0.1:27017"
//初始化
if err := initMongo(url; err != nil {
fmt.Println("连接失败!err:", err
return
}
// 获取collection
detection_coll := Client.Database("test".Collection("user"
detectionIds := []string{"jeff001", "jeff002"}
filter := bson.D{{Key: "name", Value: bson.D{{Key: "$in", Value: detectionIds}}}}
deletedCount, err := deleteOne(detection_coll, filter
if err != nil {
fmt.Println(err
return
}
fmt.Println("删除数量:", deletedCount
}