数据库

go mongo-driver动态条件

月盾
在go mongo中查询是使用的是bson.M类型的条件,但是直接使用时无法动态添加条件,只能初始化赋值,bson.M其实就是map类型,只能使用someMap[“someKey”]=“someValue” 的形式添加,这样的话只能是用if判断字段的值来决定是否添加map key/value,写起来比较繁琐。还有一种是利用结构体转换为bson.M来实现。 //构造一个查询结构体 search := User{ ID: id, Name: name, Age: age, } //构造一个条件变量 condition := bson.M{} //将结构体转为字节数组,userInfo中的字段根据需要设置值,需要保证没有值时不会有默认值出现 userbyte, err := bson.Marshal(search) if err != nil { return user, err } //将字节码转为bson.M类型 bson.Unmarshal(userbyte, &condition) log.Println(condition) if err = this.mongo.Collection("user").FindOne(context.TODO(), condition).Decode(&user); err != nil { return user, err } 以上基本就实现了动态条件查询的效果,其中: search := User{ ID: id, Name: name, Age: age, } search结构中的字段可能值为空,假设在前端并未传递age字段,那么最终condition=map[id:xxx,name:xxx],并不会出现age:0这个的字段,有效避免了零值情况。

免费的mongodb集群

月盾
mongodb提供了免费的mongodb集群可用于学习使用 https://www.mongodb.com/cloud 并且有3个节点 mongodb Atlas免费集群存储空间为512M,这对于个人项目来说足够使用(本博客运行6年使用空间8M)。 本地客户端连接mongo Atlas 复制了连接字符串后直接粘贴到客户端中,替换,点击From SRV,会自动拉取集群配置,点击Test测试连接是否成功。

mongodb创建新数据库和创建用户

月盾
使用mongodb数据库时有这样的场景,使用可视化工具登陆了某个数据库blogs,然后又创建了数据库website,给website数据库添加用户hp_website db.createUser( {user: "hp_website",pwd: "xxxxxx",roles: [ { role: "userAdmin", db: "website" },{ role: "dbAdmin", db: "website" },{ role: "dbOwner", db: "website" } ]}) 退出后使用bbb-user登陆数据库bbb却发现登陆不上去。登陆aaa数据查看用户db.getUsers()显示 虽然创建了很多用户,但db值都是blogs,显然是不对的。即时使用use website后创建用户也是不对。 正确的做法是关闭数据库认证,使用不带--auth启动数据库,使用命令行来创建 use website db.createUser( {user: "username",pwd: "xxxxxx",roles: [ { role: "userAdmin", db: "website" },{ role: "dbAdmin", db: "website" },{ role: "dbOwner", db: "website" } ]}) 这样就可以登录了。由于数据库和用户名是绑定的,只有确保用户是创建在对应数据库上才行。

linux修改MySQL 5.7.22字符集为utf8

月盾
网上也找了很多方案结果就是奇葩的不成功,最后直接修改/etc/mysql/mysql.conf.d/mysqld.cnf成功了。 在该文件最后添加 default-storage-engine=INNODB character-set-server=utf8 collation-server=utf8_general_ci 重启成功。 这是本地虚拟机里的mysql mysql> show variables like "character%"; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 完全正确,但是修改阿里云服务器以后还是有点小问题 character_set_database这一项还是latin1,不过似乎并不影响。 友情提示:纠正了mysql字符集发现新建的表还是latin1字符集,那有可能是该数据库本身的字符集就不对,可以试着看看。

mongodb forEach替换文本

月盾
最近七牛云存储要收回测试域名,但是我的博客中图片使用了这些测试域名,所以要替换掉,避免图片不可访问。在文档中没有找到可以直接替换的方法,所以就使用了mongodb的forEach循环替换。 首先用正则查询法查出使用了测试域名的文档,然后forEach循环,在每个循环中使用js的正则替换函数将域名替换掉,最后再保存该文档即可。 db.getCollection('blogs').find({content:{$regex:/hopefully.qiniudn.com/}}).forEach(function(item){ item.content = item.content.replace(/hopefully.qiniudn.com/g, 'hopefully-img.yuedun.wang') db.getCollection('blogs').save(item) print(">>", item.content); })

mongoose查询没有响应

月盾
使用mongoose建立了连接以后,通过model查询数据,如:testModel.find(),既不报错又不返回数据。 const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_database'); 使用mongoose.connect连接产生在mongoose.connection上,使用mongoose.createConnection是反回一个连接对象,建立model的时候需要使用这个连接才有效,此时使用mongoose.model是无效的。 const conn = mongoose.createConnection('your connection string'); const MyModel = conn.model('ModelName', schema); const m = new MyModel; m.save(); // 可以工作 vs const conn = mongoose.createConnection('your connection string'); const MyModel = mongoose.model('ModelName', schema); const m = new MyModel; m.save(); // 不能工作

open() is deprecated in mongoose >= 4.11.0, use openUri()

月盾
`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client Db.prototype.authenticate method will no longer be available in the next major release 3.x as MongoDB 3.6 will only allow auth against users in the admin db and will no longer allow multiple credentials on a socket. Please authenticate using MongoClient.connect with auth credentials. 修改连接参数: url = `mongodb://${this.username}:${this.password}@${this.host}:${this.port}/${this.dbName}`; const opts = { // autoReconnect: false,//默认true // reconnectTries: 30,//尝试重连,默认30次 // reconnectInterval: 1000, //重连间隔,默认1000毫秒 loggerLevel: "warn", //error/warn/info/debug useMongoClient: true }; mongoose.

mongoose自动添加createdAt和updatedAt

月盾
export var CommentSchema: Schema = new Schema({ Id: String, content: String, status: { type: Boolean, default: true } }, { timestamps: true}); 添加{ timestamps: true}选项即可,如果需要自定义属性名称可以直接指定: { timestamps: {createdAt:'created_at', updatedAt:'updated_at'}}

Mongodb和mongoose模糊查询

月盾
需求说明:在mongdb中使用模糊查询,就像sql中的like查询,在where条件中使用模糊匹配,当然最重要的是需要模糊查询的字符串是动态传入的 以一篇文章为例,content字段为文章内容,我们要查询文章内容中包含Nodejs关键字的文章 mongodb中查询 select * from articles where content like '%Nodejs%'; db.articles.find( { content: /Nodejs/i } ) Article.find({ content: /Nodejs/i}, function (err, docs) {}); 这种写法是一种简写操作,需要注意的是不能带双引号,带了双引号就成了字符串。但是这种写法是用/包裹了一个字符串类型的关键字,在实际程序是动态传入的,比如: var a="Nodejs" ; Article.find({ content: /a/i}, function (err, docs) {}); 此时会把"a"当做要查询的关键字而不是"Nodejs",所以这时还是需要用到完整的查询方式,就是使用$regex关键字,还有$options选项 var text = 'Nodejs';//动态传入的变量 Article.find({ content: { $regex: text, $options: 'i' }}, function (err, docs) {}); $options选项值: i 大小写不敏感 m $regex包含正则^,$符号的表达式 x 忽略空格 s 允许逗点匹配所有字符串 其实$regex就是正则表达式的写法 查找数组中的字段: contacts:{ [ { address: "address1", name: "张三" }, { address: "address2", name: "李四" }, .

Mongodb和mongoose聚合查询

月盾
mongdb查询某一字段sum值 需求说明:articles有一个字段pv记录了该文章的访问量,现在要统计所有文章访问量,类似于sql中的sum统计 mongodb中查询 select sum(pv) from articles; db.articles.aggregate([{$group:{_id:null,pv:{$sum:"$pv"}}}]); 结果:{ "_id" : null, "pv" : 2 } select sum(pv) from articles where createDate <= '2016-10-20'; db.articles.aggregate([{$match:{createDate:{$lte:"2016-10-20"}}},{$group:{_id:null,pv:{$sum:"$pv"}}}]); 结果:{ "_id" : null, "pv" : 9 } select sum(pv) from articles where category = 'Nodejs'; db.articles.aggregate([{$match:{category:"Nodejs"}},{$group:{_id:null,pv:{$sum:"$pv"}}}]); 结果:{ "_id" : null, "pv" : 7 } 需要注意$match和$group的顺序,反了是不行的,因为这是Aggregation Pipeline(管道流) mongoose实现方式,与上面sql的顺序对应: Article.aggregate({ $group: { _id: null, pvCount: { $sum: '$pv' }}}, function(err, doc) { console.log("1", doc); }); Article.