关于MongoDB的查询语句记录

之前写过几篇有关MongoDB的文章,主要是记录一些当时碰到的问题和解决思路。本篇文章主要记录一些MongoDB的常用命令和查询语句。以便不用每次用到了再去搜百度(有时候能不能搜到还要看运气)。

创建MongoDB用户和密码

很多朋友创建了MongoDB以后就裸奔,这是万万使不得的。当我们第一次启动MongoDB的时候是没有用户名密码的,因此可以直接启动(参考MongoDB手册)。命令如下:

./bin/mongod --port 27017 --bind_ip 0.0.0.0 --fork --dbpath /data/db --logpath /data/logs/mongod.log --logappend 

创建读写用户权限

接下来我们登陆MongoDB以后(默认是以管理员权限登陆的),分别创建三个用户。以下为登陆新建的MongoDB:

mongo --port 27017

#1. 创建管理员用户
首先我们要选择要操作的数据库。创建用户的话,统一在admin中创建。另外在创建用户的过程中,需要指定该用户的权限和对应该权限的数据库。以下是创建管理员账户,所以对应的权限是root,对应的数据库是admin。

use admin;
db.createUser(
{
    user: "mongo_root",
    pwd: "Admin$2020",
    roles: [ { role: "root", db: "admin" }],
    passwordDigestor: "server"
  }
)

#2. 创建读写权限用户
接下来我们为我们业务相关的数据库创建一个读写用户,用户名为readwrite-user,密码为ReadWrite$2020,权限为读写,对应的数据库名称为mybank。

use mybank;
db.createUser(
{
    user: "readwrite-user",
    pwd: "ReadWrite$2020",
    roles: [{role: "readWrite", db: "mybank"}]
})

#3. 创建只读权限用户
随后,我们为我们业务相关的数据库创建一个只读用户,用户名为readeronly-user,密码为ReadOnly$2020,权限为只读,对应的数据库名称为mybank。

use mybank;
db.createUser(
{
    user: "readeronly-user",
    pwd: "ReadOnly$2020",
    roles: [{role: "read", db: "mybank"}]
})

#4. 删除用户
如果创建用户错误,我们可以删除用户并重新创建。注意删除用户,需要至少userAdminAnyDatabase用户登陆并操作:

use admin;
db.system.users.remove({user:"readeronly-user"})
# 查看用户列表
db.system.users.find()

开启MongoDB身份认证

用户创建好以后,我们需要重启MongoDB并且开启身份认证。

db.adminCommand( { shutdown: 1 } )
./bin/mongod --auth --port 27017 --bind_ip 0.0.0.0 --fork --dbpath /data/db --logpath /data/logs/mongod.log --logappend 

使用用户名密码连接MongoDB

开启了身份认证以后,我们可以分别用三个不同的账号登陆到MongoDB数据库中:

./mongo 127.0.0.1:27017 -u "mongo_root" -p "Admin$2020" --authenticationDatabase "admin"
./mongo 127.0.0.1:27017 -u "readwrite-user" -p "ReadWrite$2020" --authenticationDatabase "mybank"
./mongo 127.0.0.1:27017 -u "readeronly-user" -p "ReadOnly$2020" --authenticationDatabase "mybank"

查看MongoDB数据库和Collection的状态

查看MongoDB数据库,或者数据库中的Collection的状态,使用的命令是不一样的。

查看MongoDB数据库状态

我们可以使用以下命令查看MongoDB数据库mybank状态:

use mybank;
db.stats();

返回的结果为:

{
“db” : “mybank”,//当前数据库
“collections” : 23,//当前数据库多少表
“views” : 0,
“objects” : 2164, //当前数据库所有表多少条数据
“avgObjSize” : 5579.812384473198, //每条数据的平均大小
“dataSize” : 12074714, //所有数据的总大小
“storageSize” : 9441280, //所有数据占的磁盘大小
“numExtents” : 0,
“indexes” : 23, //索引数
“indexSize” : 765952, //索引大小
“fsUsedSize” : 5157105664,
“fsTotalSize” : 85222670336,
“ok” : 1
}

查看MongoDB数据库中Collection状态

我们可以使用以下命令查看数据库中Collection状态:

db.getCollection('user-account').stats()

由于这个信息量比较大,我们就不贴样例数据了。

备份和恢复MongoDB数据库

我们可以一条命令备份或者恢复整个MongoDB中所有的数据库和Collection,也可以分库分表备份。

整库备份MongoDB

./mongodump --username mongo_root --password "Admin$2020" --authenticationDatabase "admin" --out backup

整库恢复MongoDB

./mongorestore --username mongo_root --password "Admin$2020" --authenticationDatabase "admin" --dir backup

分库分表备份MongoDB

./mongodump --username mongo_root --password "Admin$2020" --authenticationDatabase "admin" --collection user-account --db mybank --out backup

分库分表恢复MongoDB

./mongorestore --username mongo_root --password "Admin$2020" --authenticationDatabase "admin"  --db mybank --collection user-account /backup/mybank/user-account.bson

在MongoDB中使用Aggregate聚合

以下代码是在mybank的名为user的Collection中,寻找存在age(年龄)字段的用户,并且统计不同age中用户数量。

db.getCollection("user").aggregate([
    {$match: {age: { $exists: true }}},
    {$project: {'age':1}},
    {$sort: {create_date: -1}},
    {$group: {"_id": "$age",sum: {$sum: 1}}}
])

Aggregate案例#2
以下代码是在名为news的Collection中,寻找在2020年1月份中,网易新闻标题与“冠状病毒”相关的新闻。

var fromDate = new Date('2020-01-01 00:00:00');
var fromDateInt = fromDate.getTime()/1000;

var toDate = new Date('2020-02-01 00:00:00');
var toDateInt = toDate.getTime()/1000;

db.news.aggregate([
    {$match: {_id: { $gt: ObjectId(fromDateInt), $lt: ObjectId(toDateInt) }}},
    {$sort: {_id: 1}},
    {$match: {"url": {$regex: "163.com"}}
    {$match: {"news_title": {$regex: "冠状病毒"}}
])

Aggregate案例#3
在aggregate中使用hint,能够强制aggregate语句使用指定的索引,能够有效的提升查询速度。之前在《单台MongoDB服务器的不可承受之重》中详细说明了Mongodb使用索引的情况。

var fromDate = new Date('2020-01-01 00:00:00');
var fromDateInt = fromDate.getTime()/1000;

var toDate = new Date('2020-02-01 00:00:00');
var toDateInt = toDate.getTime()/1000;

db.news.aggregate([
    {$match: {_id: { $gt: ObjectId(fromDateInt), $lt: ObjectId(toDateInt) }, site_id:8898}},
    {$sort: {_id: 1}},
    {$match: {"url": {$regex: "163.com"}}
    {$match: {"news_title": {$regex: "冠状病毒"}}
], {hint: {_id:-1, site_id:1}})

上段代码中使用_id和site_id两个索引字段进行检索,大大提高查询速度。

在MongoDB中使用MapReduce

以下是使用MapReduce的一个案例,也是在名为user的Collection中,寻找存在age(年龄)字段的用户,并且统计不同age中用户数量,最后把结果存到名为result的Collection中。

db.getCollection("user").mapReduce(
    function() { emit(this.age, 1); }, 
    function(key, values) {return Array.sum(values)}, 
    {  
        query:{age: { $exists: true }},
        out:"result" //save to result collection
    }
)

另外,在Google中搜到一篇不错的文章(其实没有细看),也可以参考:MongoDB中使用MapReduce来进行聚合操作。另外,在MongoDB手册中也有大量关于MapReduce使用案例

MapReduce案例#2
统计url是否重复,存到result里面去:

db.getCollection("website").mapReduce(
    function() { emit(this.url, 1); }, 
    function(key, values) {return Array.sum(values)}, 
    {  
        query:{url: { $exists: true }},
        out:"result" //save to temp collection
    }
)

MongoDB中常用搜素

以下是一些常用的搜索方法,比较简单就不解释了,大家可以自己看。

db.getCollection("news").find({source:{$regex: "163.com"}}).count();
db.getCollection("news").find({source:{$regex: "163.com"}}).projection({_id:1, url:1, title:1}).sort({_id:1}).skip(10).limit(10);
db.getCollection("news").find({source:"https://news.163.com", create_date:{$lt:ISODate("2020-01-10T16:00:00.000Z")}}).count()
db.getCollection("news").remove({source:"https://news.163.com", create_date:{$gte:ISODate("2019-05-06T16:00:00.000Z")}})

在MongoDB中可以定义函数

以下是定义一个搜索Collection的函数,如果Collection名字中包含user就打印出来。

function searchTable(tableName) {
    db.getCollectionNames().forEach(function(collection) {
        // find the last item in a collection
        if(collection.indexOf(tableName) != -1) {
            print(collection)
        }
    })
}
searchTable("user")
Captain QR Code

扫码联系船长

发表回复

您的电子邮箱地址不会被公开。