MongoDB

安装

参照官方文档:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/#configure-selinux
Configure SELinux根据情况可以忽略
macOS安装参照: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/

启动服务

启动服务后,发现状态错误,错误码是:Unexpected mongo exit code 48
可能是默认端口27017被占用,kill之后重新启动
处理办法参照Unexpected mongo exit code 48 - restarting in Meteor

shell> sudo lsof -i :27017
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mongod  26463 root    6u  IPv4 984214      0t0  TCP *:27017 (LISTEN)
shell> kill 26463
  • 配置

    The MongoDB instance stores its data files in /var/lib/mongo and its log files in /var/log/mongodb by default, and runs using the mongod user account. You can specify alternate log and data file directories in /etc/mongod.conf. See systemLog.path and storage.dbPath for additional information.

    可以自己配置日志路径和数据路径,需要自己新建日志文件,并将此两个路径修改用户组

      $ chown -R mongod:mongod <directory>
    
  • 启动和停止
    shell> service mongod start
    shell> service mongod stop
    shell> service mongod status
    shell> service mongod restart
    

shell

  • 连接远程数据库
    $ mongo "mongodb://user:password@192.168.0.87:7999/?authSource=admin"
    

    上面的命令指定了用户, 密码, host, port, authentication database
    建议去掉冒号和密码, 回车之后再输入密码, authSource是可选的, 默认是admin
    进入mongo shell,我们会看到若干警告

  • 若干问题
    shell> mongo
    MongoDB shell version v3.4.2
    connecting to: mongodb://127.0.0.1:27017
    MongoDB server version: 3.4.2
    Server has startup warnings:
    2017-02-21T14:22:10.269+0800 I STORAGE  [initandlisten]
    2017-02-21T14:22:10.269+0800 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
    2017-02-21T14:22:10.269+0800 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten]
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten]
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten]
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten]
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
    2017-02-21T14:22:10.408+0800 I CONTROL  [initandlisten]
    
    1. ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 参照http://dba.stackexchange.com/questions/160538/mongodb-unable-to-change-mongodb-storage-engine-to-wiredtiger
      简而言之:我们一般存的数据路径的文件系统是ext,但是MongoDB3.2+推荐的文件系统是WiredTiger,所以会出现此警告
      解决办法:
      • Host your dbPath on a supported filesystem other than ext4 (XFS is recommended)
      • Start your mongo shell with the --quiet parameter (which might suppress other interesting startup info / warnings)
    2. ** WARNING: Access control is not enabled for the database.

用户管理

MongoDB默认用户认证是关闭的,也就是说访问MongoDB是没有限制的,下面说明如何配置认证
参考地址:https://docs.mongodb.com/manual/tutorial/enable-authentication/

  1. 进入MongoDB shell
  2. 创建用户管理员
    use admin
    db.createUser(
      {
        user: "myUserAdmin",
        pwd: "xyz123",
        roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
      }
    )
    

    断开shell

  3. 修改配置,重新启动mongod服务 配置如下:
    security:
       authorization: enabled
    
  4. 对生产数据库创建用户 这个时候我们如果用mongo直接进入mongo shell,会发现什么都做不了,比如显示数据库,切换数据库,都会提示没有认证。所以我们需要加上用户、密码和有权限的数据库名称:
    shell> mongo -u "myUserAdmin" -p --authenticationDatabase "admin"
    

    这个用户myUserAdmin拥有管理用户和角色的权限,我们可以对生产数据库创建用户:

    use test
    db.createUser(
      {
        user: "ksxing_admin",
        pwd: "ksxing18600361214",
        roles: [ { role: "readWrite", db: "test" }]
      }
    )
    

    role可以使用MongoDB的默认role,这里创建了一个用户myTester,他对test有读写权限,(注意:必须县切换到test数据库)

  5. myTester连接和认证
    shell> mongo -u "myTester" -p --authenticationDatabase "test"
    

    链接之后我们可以切换到test,可以读写,但是创建用户,对别的数据库读写,是不行的

  6. pyMongo测试 参照http://api.mongodb.com/python/current/examples/authentication.html
    如果MongoDB没有设置认证,那么只需配置host就可以连接了
    如果设置了认证,那么就需要额外配置用户、密码、认证方式了,MongoDB的版本是3.0+的话认证方式是SCRAM-SHA-1(版本可在MongoDB shell里用db.version()来查看)
    >>> from pymongo import MongoClient
    >>> uri="mongodb://{}:{}@{}/{}?authMechanism={}".format('myTester','xyz123','127.0.0.1','test','SCRAM-SHA-1')
    >>> client = MongoClient(uri)
    >>> db=client.test
    >>> a=db.foo
    >>> b=a.find()
    >>> b.next()
    {u'y': 1.0, u'x': 1.0, u'_id': ObjectId('58ae4cca9afbf0c6ef59bb0d')}
    

备份

  1. 物理备份
    将原有数据路径整个打包复制到新的服务器路径,然后将配置文件里的数据路径指向此文件夹即可

相关命令

数据库

  • 查看数据库 show dbs
  • 使用数据库 use dbname
  • 查看collections show collections
  • 删除集合collection db.collection.drop()

查询

  • 查询 db.collectionname.find({"key": "value"})
  • 查询一条 db.collectionname.find({“key”: “value”})`
  • distinct count db.collection.distinct('field').length

索引

  • 查看索引 db.collection.getIndexes()
  • 创建索引 db.collection.ensureIndex({"resut_id": 1})

删除

  • 按条件删除记录 db.collection.remove({"result_id":"435"})
  • 删除全部记录 db.collection.remove({})
  • 删除字段
    将year_month是2021-07的数据的spi_sku_code和sale_sku_code两个字段删除
    db.revenue_aggregation_adjust.update({year_month:"2021-07"}, {$unset: {spi_sku_code:1, sale_sku_code:1}}, {multi: true})
    

更新

  • update db.collection.(<query>, <update>, <option>)
    示例, set代表更新, 如果没有set, 则替换掉了, option加上{multi:true}, 会把匹配搭配到的数据都更新, 不然只会更新一条:
    db.revenue_revoke.update({order_no: "NWBAXDU2JG9DFS58"}, {$set: {order_no: "NWBAXDU2JG9DFS58", "service_no": 559829, "sku_code": "L20100265610"}}, {multi: true})

计算&汇总

  • sum
    db.revenue_aggregation.aggregate(
      {$match: {year_month: "2021-04", fin_cat_id_l2: 189}},
      {$group: {_id: null, amount: {$sum:"$received_amount"}}})
    

    aggregate方法, match查询, group+sum求和, _id: null是必须的