zoukankan      html  css  js  c++  java
  • Golang学习系列第六天:操作MongoDB

    0.  ssh连接linux(我用的centos7),略
    1.  安装MongoDB 
    可以直接到MongoDB官网https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat-tarball/根据样板安装:,可根据自己的电脑操作系统下载对应的版本,我下载的是mongodb-linux-x86_64-4.0.0.tgz安装包,不过也可以直接点击下面这个链接直接下载 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.0.tgz,即

    wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.0.tgz

    下载完毕后解压缩

    [root@master dgm]# tar -zxf mongodb-linux-x86_64-4.0.0.tgz

    名字那么长,可以进行重命名:

    [root@master dgm]# mv mongodb-linux-x86_64-4.0.0 mongodb
    

    进入到mongodb主目录下:

    cd mongodb

    分别建配置文件、数据目录、日志文件

    建立配置文件

    vim mongodb.conf

    键入以下内容

    #端口号
    port=27017
    #db目录
    dbpath=/dgm/mongodb/data/db
    #日志目录
    logpath=/dgm/mongodb/logs/mongodb.log
    #后台
    fork=true
    #日志输出
    logappend=true
    #允许远程IP连接
    bind_ip=0.0.0.0
    

    注意路径根据自己电脑的实际情况填写

    建立数据目录和日志文件

    [root@master mongodb]# mkdir -p data/db logs
    [root@master mongodb]# touch logs/mongodb.log
    

    编辑环境配置 

    vim /etc/profile

    追加以下内容:

    切记路径按实际情况写

    source /etc/profile

    启动mongodb测试

    [root@master mongodb]# mongod --config mongodb.conf 
    

    最后连接测试

    [root@master mongodb]# mongo
    

    为了安全起见,我们需要设置相应的用户名和密码。

    创建数据库系统管理员

    > use admin
    switched to db admin
    > db.createUser({ user: "admin", pwd: "12345678", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })
    Successfully added user: {
    	"user" : "admin",
    	"roles" : [
    		{
    			"role" : "userAdminAnyDatabase",
    			"db" : "admin"
    		}
    	]
    }
    > db.auth("admin", "12345678")
    1
    

     修改mongodb配置追加认证标志

    ## 是否以安全认证方式运行,默认是不认证的非安全方式
    #noauth = true
    auth = true
    

    然后重启mongodb服务

     再次通过shell进入mongodb,创建需要管理的mongodb 数据的账号密码,此处是库是douyin,用户名是root,密码87654321

    [root@master mongorest]# mongo
    > use admin
    switched to db admin
    > db.auth("admin", "12345678")
    1
    > use douyin
    switched to db douyin
    > db.createUser({ user: "root", pwd: "87654321", roles: [{ role: "dbOwner", db: "douyin" }] })
    Successfully added user: {
    	"user" : "root",
    	"roles" : [
    		{
    			"role" : "dbOwner",
    			"db" : "douyin"
    		}
    	]
    }
    > use admin
    switched to db admin
    > db.system.users.find()
    { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "Qp+6YETcIsDyrPPwQVtWHQ==", "storedKey" : "0X27QePHJknrd+5qg4Ai5TeEWjg=", "serverKey" : "ZYRXkrQfJY875GC1qf76xAmBFow=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "E3LYqVegf93pTNjwNqXh4Gy8zQ1qNXXz0HtHHw==", "storedKey" : "yUZq7I9/w8Kf6fLu6Q8OqJcKNv77KUDmvGo4gEGi5ng=", "serverKey" : "+sNL0T/gfa+B+HoNSeid+HCC7OulvZlvSi2FDtE3wfk=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
    { "_id" : "douyin.root", "user" : "root", "db" : "douyin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "gVHTUMMMC38slLBW15kxPw==", "storedKey" : "591b17pCtkEZcVXf7ZO/Ll4DPAs=", "serverKey" : "vd5w+StBi9eXfViwWY30tc66lmo=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "2CHwq56N9MLts2v+PSqN3qs6tpWX1BKHY0aTDA==", "storedKey" : "2v5I/nnNoGVst2tTljoQs34z7bDNZS4euv6nAFZGxyc=", "serverKey" : "/F2xcR86DH4ErEEEbDyprmm1ttnl1o6sniWrj3vjjTY=" } }, "roles" : [ { "role" : "dbOwner", "db" : "douyin" } ] }
    > exit
    

     测试密码权限是否生效

    先看失败的尝试案例

    [root@master mongorest]# mongo
    MongoDB shell version v4.0.0
    connecting to: mongodb://127.0.0.1:27017
    MongoDB server version: 4.0.0
    > use douyin
    switched to db douyin
    > show collections
    Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
    > db.douyin.find()
    Error: error: {
    	"ok" : 0,
    	"errmsg" : "command find requires authentication",
    	"code" : 13,
    	"codeName" : "Unauthorized"
    }
    > 
    

    再看成功的案例

    [root@master mongorest]# mongo "mongodb://root:87654321@127.0.0.1:27017/douyin"
    MongoDB shell version v4.0.0
    connecting to: mongodb://127.0.0.1:27017/douyin
    MongoDB server version: 4.0.0
    > show collections
    douyin
    > db.douyin.find()
    { "_id" : ObjectId("5f083625b8b307c7e889f276") }
    { "_id" : ObjectId("5f08365cb8b307c7e889f277"), "name" : "dongguangming", "age" : 31 }
    > 
    

    很好,权限认证通过了,可以查询数据记录 

    2.  golang操作MongoDB

    2.1  增加书籍接口

    新建go文件mongdb-add.go,键入以下代码

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    	"net/http"
    
    	"goji.io"
    	"goji.io/pat"
    	"gopkg.in/mgo.v2"
    )
    
    func ErrorWithJSON(w http.ResponseWriter, message string, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	fmt.Fprintf(w, "{message: %q}", message)
    }
    
    func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	w.Write(json)
    }
    
    type Book struct {
    	ISBN    string   `json:"isbn"`
    	Title   string   `json:"title"`
    	Authors []string `json:"authors"`
    	Price   string   `json:"price"`
    }
    
    func main() {
    	session, err := mgo.Dial("mongodb://root:87654321@127.0.0.1:27017/douyin")
    	if err != nil {
    		panic(err)
    	}
    	defer session.Close()
    
    	session.SetMode(mgo.Monotonic, true)
    	ensureIndex(session)
    
    	mux := goji.NewMux()
    	mux.HandleFunc(pat.Post("/books"), addBook(session))
    	http.ListenAndServe("192.168.8.200:8888", mux)
    }
    
    func ensureIndex(s *mgo.Session) {
    	session := s.Copy()
    	defer session.Close()
    
    	c := session.DB("douyin").C("books")
    
    	index := mgo.Index{
    		Key:        []string{"isbn"},
    		Unique:     true,
    		DropDups:   true,
    		Background: true,
    		Sparse:     true,
    	}
    	err := c.EnsureIndex(index)
    	if err != nil {
    		panic(err)
    	}
    }
    
    
    func addBook(s *mgo.Session) func(w http.ResponseWriter, r *http.Request) {
    	return func(w http.ResponseWriter, r *http.Request) {
    		session := s.Copy()
    		defer session.Close()
    
    		var book Book
    		decoder := json.NewDecoder(r.Body)
    		err := decoder.Decode(&book)
    		if err != nil {
    			ErrorWithJSON(w, "数据格式不对", http.StatusBadRequest)
    			return
    		}
    
    		c := session.DB("douyin").C("books")
    
    		err = c.Insert(book)
    		if err != nil {
    			if mgo.IsDup(err) {
    				ErrorWithJSON(w, "书的isbn已存在", http.StatusBadRequest)
    				return
    			}
    
    			ErrorWithJSON(w, "服务器错误", http.StatusInternalServerError)
    			log.Println("添加书失败!!!: ", err)
    			return
    		}
    
    		w.Header().Set("Content-Type", "application/json")
    		w.Header().Set("Location", r.URL.Path+"/"+book.ISBN)
    		w.WriteHeader(http.StatusCreated)
    	}
    }
    
    

    然后就就执行以上程序,

    go run  mongdb-add.go

    打开postman测试

    查询数据库是否已存在

    2.2  查询单书籍接口

    新建go文件mongdb-select.go,键入以下代码

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    	"net/http"
    
    	"goji.io"
    	"goji.io/pat"
    	"gopkg.in/mgo.v2"
        "gopkg.in/mgo.v2/bson"
    )
    
    func ErrorWithJSON(w http.ResponseWriter, message string, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	fmt.Fprintf(w, "{message: %q}", message)
    }
    
    func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	w.Write(json)
    }
    
    type Book struct {
    	ISBN    string   `json:"isbn"`
    	Title   string   `json:"title"`
    	Authors []string `json:"authors"`
    	Price   string   `json:"price"`
    }
    
    func main() {
    	session, err := mgo.Dial("mongodb://root:87654321@127.0.0.1:27017/douyin")
    	if err != nil {
    		panic(err)
    	}
    	defer session.Close()
    
    	session.SetMode(mgo.Monotonic, true)
    	ensureIndex(session)
    
    	mux := goji.NewMux()
        mux.HandleFunc(pat.Get("/books/:isbn"), bookByISBN(session))	 
        http.ListenAndServe("192.168.8.200:8888", mux)
    }
    
    func ensureIndex(s *mgo.Session) {
    	session := s.Copy()
    	defer session.Close()
    
    	c := session.DB("douyin").C("books")
    
    	index := mgo.Index{
    		Key:        []string{"isbn"},
    		Unique:     true,
    		DropDups:   true,
    		Background: true,
    		Sparse:     true,
    	}
    	err := c.EnsureIndex(index)
    	if err != nil {
    		panic(err)
    	}
    }
    
    
    func bookByISBN(s *mgo.Session) func(w http.ResponseWriter, r *http.Request) {
    	return func(w http.ResponseWriter, r *http.Request) {
    		session := s.Copy()
    		defer session.Close()
    
    		isbn := pat.Param(r, "isbn")
    
    		c := session.DB("store").C("books")
    
    		var book Book
    		err := c.Find(bson.M{"isbn": isbn}).One(&book)
    		if err != nil {
    			ErrorWithJSON(w, "数据库错误", http.StatusInternalServerError)
    			log.Println("查找isbn的书失败: ", err)
    			return
    		}
    
    		if book.ISBN == "" {
    			ErrorWithJSON(w, "书不存在", http.StatusNotFound)
    			return
    		}
    
    		respBody, err := json.MarshalIndent(book, "", "  ")
    		if err != nil {
    			log.Fatal(err)
    		}
    
    		ResponseWithJSON(w, respBody, http.StatusOK)
    	}
    }
    
    
    

    执行程序

    go run  mongdb-select.go

    继续用postman测试接口

     

    2.3  修改单书籍接口

    新建go文件mongdb-update.go,键入以下代码

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    	"net/http"
    
    	"goji.io"
    	"goji.io/pat"
    	"gopkg.in/mgo.v2"
        "gopkg.in/mgo.v2/bson"
    )
    
    func ErrorWithJSON(w http.ResponseWriter, message string, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	fmt.Fprintf(w, "{message: %q}", message)
    }
    
    func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	w.Write(json)
    }
    
    type Book struct {
    	ISBN    string   `json:"isbn"`
    	Title   string   `json:"title"`
    	Authors []string `json:"authors"`
    	Price   string   `json:"price"`
    }
    
    func main() {
    	session, err := mgo.Dial("mongodb://root:87654321@127.0.0.1:27017/douyin")
    	if err != nil {
    		panic(err)
    	}
    	defer session.Close()
    
    	session.SetMode(mgo.Monotonic, true)
    	ensureIndex(session)
    
    	mux := goji.NewMux()
        mux.HandleFunc(pat.Put("/books/:isbn"), updateBook(session))	 
        http.ListenAndServe("192.168.8.200:8888", mux)
    }
    
    func ensureIndex(s *mgo.Session) {
    	session := s.Copy()
    	defer session.Close()
    
    	c := session.DB("douyin").C("books")
    
    	index := mgo.Index{
    		Key:        []string{"isbn"},
    		Unique:     true,
    		DropDups:   true,
    		Background: true,
    		Sparse:     true,
    	}
    	err := c.EnsureIndex(index)
    	if err != nil {
    		panic(err)
    	}
    }
    
    
    func updateBook(s *mgo.Session) func(w http.ResponseWriter, r *http.Request) {
    	return func(w http.ResponseWriter, r *http.Request) {
    		session := s.Copy()
    		defer session.Close()
    
    		isbn := pat.Param(r, "isbn")
    
    		var book Book
    		decoder := json.NewDecoder(r.Body)
    		err := decoder.Decode(&book)
    		if err != nil {
    			ErrorWithJSON(w, "Incorrect body", http.StatusBadRequest)
    			return
    		}
    
    		c := session.DB("douyin").C("books")
    
    		err = c.Update(bson.M{"isbn": isbn}, &book)
    		if err != nil {
    			switch err {
    			default:
    				ErrorWithJSON(w, "Database error", http.StatusInternalServerError)
    				log.Println("Failed update book: ", err)
    				return
    			case mgo.ErrNotFound:
    				ErrorWithJSON(w, "Book not found", http.StatusNotFound)
    				return
    			}
    		}
    
    		w.WriteHeader(http.StatusNoContent)
    	}
    }
    
    

    执行以上程序 

    go run  mongdb-update.go

     postman继续测试

    再此查询isbn为1234567890的信息

    2.4  查询所有书籍接口

    新建go文件mongdb-all.go,键入以下代码

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    	"net/http"
    
    	"goji.io"
    	"goji.io/pat"
    	"gopkg.in/mgo.v2"
             "gopkg.in/mgo.v2/bson"
    )
    
    func ErrorWithJSON(w http.ResponseWriter, message string, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	fmt.Fprintf(w, "{message: %q}", message)
    }
    
    func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	w.Write(json)
    }
    
    type Book struct {
    	ISBN    string   `json:"isbn"`
    	Title   string   `json:"title"`
    	Authors []string `json:"authors"`
    	Price   string   `json:"price"`
    }
    
    func main() {
    	session, err := mgo.Dial("mongodb://root:87654321@127.0.0.1:27017/douyin")
    	if err != nil {
    		panic(err)
    	}
    	defer session.Close()
    
    	session.SetMode(mgo.Monotonic, true)
    	ensureIndex(session)
    
    	mux := goji.NewMux()
        	mux.HandleFunc(pat.Get("/books"), allBooks(session))
    
        http.ListenAndServe("192.168.8.200:8889", mux)
    }
    
    func ensureIndex(s *mgo.Session) {
    	session := s.Copy()
    	defer session.Close()
    
    	c := session.DB("douyin").C("books")
    
    	index := mgo.Index{
    		Key:        []string{"isbn"},
    		Unique:     true,
    		DropDups:   true,
    		Background: true,
    		Sparse:     true,
    	}
    	err := c.EnsureIndex(index)
    	if err != nil {
    		panic(err)
    	}
    }
    
    func allBooks(s *mgo.Session) func(w http.ResponseWriter, r *http.Request) {
    	return func(w http.ResponseWriter, r *http.Request) {
    		session := s.Copy()
    		defer session.Close()
    
    		c := session.DB("douyin").C("books")
    
    		var books []Book
    		err := c.Find(bson.M{}).All(&books)
    		if err != nil {
    			ErrorWithJSON(w, "Database error", http.StatusInternalServerError)
    			log.Println("Failed get all books: ", err)
    			return
    		}
    
    		respBody, err := json.MarshalIndent(books, "", "  ")
    		if err != nil {
    			log.Fatal(err)
    		}
    
    		ResponseWithJSON(w, respBody, http.StatusOK)
    	}
    }
    

    运行该程序

    go run  mongdb-all.go

    打开postman或浏览器

    2.5 删除单书籍接口

    新建go文件mongdb-delete.go(根据isbn编号),键入以下代码

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    
    	"goji.io"
    	"goji.io/pat"
    	"gopkg.in/mgo.v2"
             "gopkg.in/mgo.v2/bson"
    )
    
    func ErrorWithJSON(w http.ResponseWriter, message string, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	fmt.Fprintf(w, "{message: %q}", message)
    }
    
    func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
    	w.Header().Set("Content-Type", "application/json; charset=utf-8")
    	w.WriteHeader(code)
    	w.Write(json)
    }
    
    type Book struct {
    	ISBN    string   `json:"isbn"`
    	Title   string   `json:"title"`
    	Authors []string `json:"authors"`
    	Price   string   `json:"price"`
    }
    
    func main() {
    	session, err := mgo.Dial("mongodb://root:87654321@127.0.0.1:27017/douyin")
    	if err != nil {
    		panic(err)
    	}
    	defer session.Close()
    
    	session.SetMode(mgo.Monotonic, true)
    	ensureIndex(session)
    
    	mux := goji.NewMux()
        	mux.HandleFunc(pat.Delete("/books/:isbn"), deleteBook(session))
    
        http.ListenAndServe("192.168.8.200:8889", mux)
    }
    
    func ensureIndex(s *mgo.Session) {
    	session := s.Copy()
    	defer session.Close()
    
    	c := session.DB("douyin").C("books")
    
    	index := mgo.Index{
    		Key:        []string{"isbn"},
    		Unique:     true,
    		DropDups:   true,
    		Background: true,
    		Sparse:     true,
    	}
    	err := c.EnsureIndex(index)
    	if err != nil {
    		panic(err)
    	}
    }
    func deleteBook(s *mgo.Session) func(w http.ResponseWriter, r *http.Request) {
    	return func(w http.ResponseWriter, r *http.Request) {
    		session := s.Copy()
    		defer session.Close()
    
    		isbn := pat.Param(r, "isbn")
    
    		c := session.DB("douyin").C("books")
    
    		err := c.Remove(bson.M{"isbn": isbn})
    		if err != nil {
    			switch err {
    			default:
    				ErrorWithJSON(w, "Database error", http.StatusInternalServerError)
    				log.Println("Failed delete book: ", err)
    				return
    			case mgo.ErrNotFound:
    				ErrorWithJSON(w, "Book not found", http.StatusNotFound)
    				return
    			}
    		}
    
    		w.WriteHeader(http.StatusNoContent)
    	}
    }
    

    执行以上程序

    go run  mongdb-delete.go

    用postman测试删除

     

    然后去数据库查看是否还有该isbn为1234567890的书籍

     

     

    最后加上一点,mongodb和其他数据库mysql、postgresql一样面临数据多需要分页的情况,类比2012年做的车辆GPS+3G视频监控调度系统(每辆车只要一启动开火,就会产生大量的视频数据,一运行,就会产生很多的gps数据上传到数据中心,可以通过系统实时查看车上的视频情况和运行轨迹),被央视广泛宣传推广。数据量不是一般的多!!!视频数据还好,一会月没有盗窃案件事件就删除了(那时没有大数据的理念,也没有用人工智能训练数据的初衷,并没有存下来,且存储和内存还是很贵的,不像现在服务器几十上百G内存、存储空间以T为单位),可每辆车每天的gps数据却是长久保存的,要是哪天想回看在地图上的历史轨迹,就要从很多数据里检索,有点像后来衍生出的ofo、摩拜、滴滴和其他共享车平台。

    附代码已上传github: https://github.com/dongguangming/golang-learn/tree/master/go-mongodb

     

    参考:

    1. The myth of NoSQL (vs. RDBMS) “joins dont scale”

    2. How To Install MongoDB on CentOS 7 https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-centos-7

    3. mongodb设置密码 https://cloud.tencent.com/developer/article/1401326

    4.  MongoDB Configuration File Options https://docs.mongodb.com/manual/reference/configuration-options/#security-options

    5. The mongo Shell  https://docs.mongodb.com/manual/mongo/

    6.  How To Build Microservice With MongoDB In Golang  https://goinbigdata.com/how-to-build-microservice-with-mongodb-in-golang/
    7. How to paginate with MongoDB https://rabbitoncode.com/big-data/2019/10/11/pagination-mongo/

    8. API Paging Built The Right Way https://engineering.mixmax.com/blog/api-paging-built-the-right-way/

    9. Golang, Gin & MongoDB – Building microservices easily https://blog.codecentric.de/en/2020/04/golang-gin-mongodb-building-microservices-easily/

    10. Paging with the Bucket Pattern - Part 1  https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-1

    11. 海量数据的分页怎么破 https://mongoing.com/archives/25469

    12. Pagination for MSSQL & MongoDB https://piotrgankiewicz.com/2016/04/19/pagination-for-mssql-mongodb/

  • 相关阅读:
    2018-2019-2 20165232 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
    2018-2019 20165232 Exp5 MSF基础应用
    2018-2019-2 网络对抗技术 20165232 Exp4 恶意代码分析
    2018-2019-2 网络对抗技术 20165232 Exp3 免杀原理与实践
    2018-2019-2 网络对抗技术 20165232 Exp2 后门原理与实践
    2018-2019-2 20165232《网络对抗技术》Exp1 缓冲区溢出实验
    20165232 week1 kali安装
    2018-2019-2 20165205 网络对抗技术 Exp9 Web安全基础
    2018-2019-2 网络对抗技术 20165205 Exp8 Web基础
    2018-2019-2 20165205 网络对抗技术 Exp7 网络欺诈防范
  • 原文地址:https://www.cnblogs.com/dongguangming/p/13374986.html
Copyright © 2011-2022 走看看