zoukankan      html  css  js  c++  java
  • mongodb shell和Node.js driver使用基础

    开始:

    Mongo Shell

    安装后,输入mongo进入控制台:

    //所有帮助
    > help
    //数据库的方法
    > db.help()
    > db.stats()  //当前数据库的状态,包括collections属性,显示有多少个。
    
    > show dbs  //显示所有的数据库

    Insert Document

    使用控制台insert和执行查询语法:

    db.inventory.insertMany({
       { item: "journal", qty: 25, status: "A",
           size: { h: 14, w: 21, uom: "cm" }, tags: [ "blank", "red" ] }
    })

    db.collection.insertOne()

    Query Document

    例子:

    db.inventory.find({status: "D"})

    查询嵌套属性: "field.field": value

    db.inventory.find( { "size.uom": "cm" } )

    查询在数组中的一个元素:  filed:value之一

    db.inventory.find({tags: "red"})

    查询一个数组:

    db.inventory.find( { tags: ["red", "blank"] } )

    Databases and Collections

    MongoDB在collections内存储数据记录,BSON documents等;

    collections则存在于数据库内。

    Database

    选择一个数据库:

    use myDB

    创建一个数据库

    use myNewDB
    
    db.myNewCollection1.insertOne({x: 1})

    解释:
    如果myNewDB不存在,当你第一次向这个数据库存入数据时,就会创建这个数据库。
    因此,你可以使用use方法切换到一个不存在的数据库,然后执行插入数据的操作,在mongo shell.

    insertOne方法创建了数据库myNewDB,同时也创建了collection: myNewCollection1(如果它们不存在)

    Collections

    MongoDB在collections内存储documents。

    collections 类似关系数据库的table。

    //如果collection不存在,则第一次存入数据时创建它。
    db.myNewCollection2.insertOne({ x: 1})

    明确的创建

    主要用于设置一些选项。

    // 明确创建一个collection
    // 可以设置一些选项:最大的size, documentation validatin rules。
    // 如果你不指定这些选项,就没必要使用这个方法了
    db.createCollection()

    Document Validation(version3.2新功能)

    一般来说collection无需要它的documents有相同的结构。

    即在一个collection内,documents不需要有相同的fields和数据类型。

    mongoDB是一个非关系性的数据库。

    但,3.2version 增加了这个验证功能See Schema Validation for details.

    修改Document Structure

    可以改变一个collection内的documents的结构,包括增加新fields, remove fields,或者改变field的值。


    Views(new in version3.4)

    支持创建只读的views。 从existing collections或者其他views创建。


    Documents

    相当于关系型数据库的每条记录。

    MongoDB储存数据记录的格式是 BSON.

    BSON is a binary representation of JSON documents, 比JSON的数据类型多。

    See also BSON Types.

    {
       field1: value1,
       field2: value2,
       field3: value3,
       ...
       fieldN: valueN
    }

    一个filed的值可以是任何形式的BSON数据类型:

    var mydoc = {
                   _id: ObjectId("5099803df3f4948bd2f98391"),
                   name: { first: "Alan", last: "Turing" },
                   birth: new Date('Jun 23, 1912'),
                   death: new Date('Jun 07, 1954'),
                   contribs: [ "Turing machine", "Turing test", "Turingery" ],
                   views : NumberLong(1250000)
                }

     contribes是array of strings的数据类型。

     filed names是字符串, 不能有null, 顶级的filed name不能以$开始

    Dot标记

    MongoDB使用dot来存取一个array的元素, 或者一个嵌套的document(hash)的field。


    BSON Types

    https://docs.mongodb.com/manual/reference/bson-types/ 


    摘录:

    MongoDB的数据结构


    Start Thinking in JSON

    While a table might seem like a good place to store data, as you can see from the example above, there are fields in this data set that require multiple values and would not be easy to search or display if modeled in a single column (for example – size and tags).

    In a SQL database you might solve this problem by creating a relational table.

    In MongoDB, data is stored as documents. These documents are stored in MongoDB in JSON (JavaScript Object Notation) format.

    JSON documents support embedded fields, so related data and lists of data can be stored with the document instead of an external table.

    可嵌套的fileds数据结构解决了相关的数据的查询。和关系型数据库不一样。

    一个JSON document 

    {"name": "notebook", "qty": 50}

    一个完成的JSON document: 

    rating, tags,无需像关系型数据库那样,单独使用一个table,然后设置外键,主键, 进行表的关联。

    {
     "name": "notebook",
     "qty": 50,
     "rating": [ { "score": 8 }, { "score": 9 } ],
     "size": { "height": 11, "width": 8.5, "unit": "in" },
     "status": "A",
     "tags": [ "college-ruled", "perforated"]
    }

    安装

    见之前的博客,或者

    看guide: 3种系统的安装手册:

    https://docs.mongodb.com/guides/server/install/


    Enable Authentication on MongoDB

    https://docs.mongodb.com/guides/server/auth/

    This guide describes how to enable authentication on your local MongoDB instance.

    创建用户账号。

    1.check your Environment!

    ps | grep 'mongod'
    
    //如果一个mongod instance正在运行,会看到
    //89780 ttys026  

    在控制台开启一个实例:

    mongo
    //mongo --host <HOSTNAME> --port <PORT>

    创建一个全权限的管理员:

    db.createUser(
    ...   {
    ...     user: "myUserAdmin",
    ...     pwd: "abc123",
    ...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
    ...   }
    ... )
    Successfully added user: {
        "user" : "myUserAdmin",
        "roles" : [
            {
                "role" : "userAdminAnyDatabase",
                "db" : "admin"
            }
        ]
    }

    创建一个普通的用户:

    > use admin
    //switched to db admin
    > db.createUser(
    ... {
    ...   user: 'userreadwrite',
    ...   pwd: 'abc123',
    ...   roles: [{ role: 'readWriteAnyDatabase', db: "admin"}]
    ... }
    ... )
    //Successfully added user: {
        "user" : "userreadwrite",
        "roles" : [
            {
                "role" : "readWriteAnyDatabase",
                "db" : "admin"
            }
        ]
    }

    检查你的users:

    > show users
    {
        "_id" : "admin.myUserAdmin",
        "user" : "myUserAdmin",
        "db" : "admin",
        "roles" : [
            {
                "role" : "userAdminAnyDatabase",
                "db" : "admin"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }
    {
        "_id" : "admin.userreadwrite",
        "user" : "userreadwrite",
        "db" : "admin",
        "roles" : [
            {
                "role" : "readWriteAnyDatabase",
                "db" : "admin"
            }
        ],
        "mechanisms" : [
            "SCRAM-SHA-1",
            "SCRAM-SHA-256"
        ]
    }

    退出mongo shell

    重启MongoDB实例,必须加上-auth选项。

    mongod --dbpath <path to data directory>  --auth

    登陆mongo shell使用选项:

    本例子:

    mongo -u userreadwrite -p abc123

    mongo -h:得到的参数

    Authentication Options:
      -u [ --username ] arg               username for authentication
      -p [ --password ] arg               password for authentication
      --authenticationDatabase arg        user source (defaults to dbname)
      --authenticationMechanism arg       authentication mechanism
      --gssapiServiceName arg (=mongodb)  Service name to use when authenticating
                                          using GSSAPI/Kerberos
      --gssapiHostName arg                Remote host name to use for purpose of
                                          GSSAPI/Kerberos authentication

    Connect to MongoDB

    选择开发类型deployment type: cloud云, local本地

    选择客户端:shell:

    Mongo Shell,  Compass, node.js, 等待

    使用本地开发,用Mongo Shell:

    为了能够连接到MongoDB, 你需要使用a URI string,  类似URL。

    当连接到一个MongoDB deployment, 它作为参数提供给mongo shell,Compass,和MongoDB drivers.

    如果你已经建立了一个user, 就可以使用这个用户名和密码连接:

    运行下面的代码

    $ mongod --auth  //会打开一个数据库实例,这实例要求有用户验证。
    
    //在另一个新窗口输入:
    // mongo mongodb://$[hostlist]/$[database]?authSource=$[authSource] --username $[username]
    $ mongo mongodb://localhost -u userreadwrite
    //MongoDB shell version v4.0.5
    //Enter password:  //输入密码
    //connecting to: mongodb://localhost:27017/?gssapiServiceName=mongodb
    //Implicit session: session { "id" : UUID("8c9cb343-e27c-43fa-aa28-e20097d1fabc") }
    //MongoDB server version: 4.0.5
    >

    使用插入语法:

    mongo mongodb://localhost
    $ use test
    
    //插入一条语句:
    //如果不提供_id field, MongoDB会增加_id field,值是一个ObjectId value。
    > db.inventory.insertOne( ... { ... "item": "canvas", ... "qyt": 122, ... "tags": ["cotton"], ... "size": {"height": 28, "width": 22.4, "uom": "cm"} ... } ... ) //{ // "acknowledged" : true, // "insertedId" : ObjectId("5c3ee8571b8c6250d59a4389") //}
    • 和SQL tables不一样, MongoDB collections有动态的结构。一个单一的collection可以储存不同结构的documents。
    • 和SQL不一样,不需要DDL operation 来增加或者移除fields或者修改field types。你可以直接update documents。

    使用NODE.JS连接到你的数据库实例:

    首先,安装node.js客户端,和driver:Node.js Driver documentation

    然后,得到你的MongoDB connection string(URI)

    然后,在一个脚本写代码:

    如果想要使用user登陆,见下面代码:

    //控制台
    $ mongod --auth

    Node.js脚本:

    const MongoClient = require('mongodb').MongoClient;
    const assert = require('assert');
    
    // Connection URL语法结构:
    //const url = 'mongodb://$[username]:$[password]@$[hostlist]/$[database]?authSource=$[authSource]';
    const url = `mongodb://userreadwrite:abc123@${dbHost}:${dbPort}`;
    // 使用MongoClient的类方法connect,也可以使用实例方法connect. MongoClient.connect(url, function(err, client) { assert.equal(null, err); client.close(); });

    解释:

    MongoClient.connect(url, options, callback) ->{Promise.<MongoClient>}

    1. callback是指MongoClient中的connectCallback函数,这个函数有2个参数:
      • error:   一个error实例,反应执行期间的错误。
      • client:   就是MongoClient的连接的实例。
    2. 如果没有传入callback参数,则返回Promise.<MongoClient>, Promise格式的mongoClient实例。

    实例可以使用: connect(callback) 方法,如果没有callback,则返回它自身。

    实例可以使用db(dbName, options)->{Db}

    • 创建一个新的Db实例,注意这个实例和原始实例是父子关系。

     

    使用插入语法:

    在connect block内,设置db给test database:

    const db = client.db('test')

    插入一个单一的Document:

    下面的例子插入一个新的document到inventory collection。

    db.collection("inventory").insertOne({
      item: "canvas",
      qty: 100,
      tags: ["cotton"],
      size: { h: 28, w: 35.5, uom: "cm" }
    })
    .then((result) => {
      //处理result
    })

    ⚠️如果是MongoDB实例需要验证--auth, 但连接的url字符串没有用户名和密码,那么则插入不会成功,result返回null.

    下面代码是driver3-insert.js脚本的执行结果:

    // 提供用户名和密码给url,最后
    $ node driver3-insert.js
    Connected successfully to server
    Inserted 3 documents into the collection,
     { result: { ok: 1, n: 3 },
      ops:
       [ { a: 12, _id: 5c3ef39539f6c6f359d996b9 },
         { b: 2, _id: 5c3ef39539f6c6f359d996ba },
         { b: 3, _id: 5c3ef39539f6c6f359d996bb } ],
      insertedCount: 3,
      insertedIds:
       { '0': 5c3ef39539f6c6f359d996b9,
         '1': 5c3ef39539f6c6f359d996ba,
         '2': 5c3ef39539f6c6f359d996bb } }
    // 没有提供用户名和密码或者,提供错误:
    Connected successfully to server
    Inserted 3 documents into the collection,
     null

    Node.js: Collection类的实例方法:

    insertOne() ,findAndModify(), remove(), save(), update()等大多数Collection的实例方法,

    在不传入callback时,会返回一个promise对象。


    Read Data from MongoDB

    Mongo Shell:

    $ mongo
    > use test
    //假设test database内已经有inventory collection.
    > db.inventory.find({})
    //这个查询,无需cursor 迭代,因为shell会返回所有结果。

    Node.js

    const db = client.db("test");
    
    var cursor = db.collection('inventory').find({})
    
    //迭代这个结果
    function iterateFun(doc) {
      console.log(JSON.stringify(doc, null, 4))
    }
    
    function errorFunc(error) {
      console.log(error);
    }
    
    cursor.forEach(iterateFunc, errorFunc)

    Read Data using Operators and Compound Queries

    使用or,and等语法,组合查询。

    一个问题:

    在MongoDb shell

    // 这种写法,my不能使用forEach方法。
    my = db.inventory.find({status: "D"} ) 
    
    //必须用, 才能使用forEach,而且只能用一次!!!
    var my = db.inventory.find({status: "D"} ) 

    node.js代码演示:

    //确认一下mongod开启
    $ ps | grep 'mongod'
    //没有的话
    $ mongo
    
    //写driver3-query-many.js
    
    const MongoClient = require('mongodb').MongoClient
    const assert = require('assert')
    const dbHost = '127.0.0.1'
    const dbPort = 27017
    
    const url = `mongodb://${dbHost}:${dbPort}`
    
    const dbName = 'test'
    
    const client = new MongoClient(url)
    
    client.connect(function(err) {
      assert.equal(null, err)
      console.log("Connected correctly to server")
      //设置db到test database
      const db = client.db(dbName)
    })

    在mongoDb shell中查看一下,test database是否有inventory collection及documents,

    没有的话就插入一些数据:

    //此时是在控制台
    >use test
    >db.inverntory.insert([
      { item: "journal",
        qty: 25,
        size: { h: 14, w: 21, uom: "cm" },
        status: "A"},
      { item: "notebook",
        qty: 50,
        size: { h: 8.5, w: 11, uom: "in" },
        status: "A"},
      { item: "paper",
        qty: 100,
        size: { h: 8.5, w: 11, uom: "in" },
        status: "D"},
      { item: "planner",
        qty: 75, size: { h: 22.85, w: 30, uom: "cm" },
        status: "D"},
      { item: "postcard",
        qty: 45,
        size: { h: 10, w: 15.25, uom: "cm" },
        status: "A"}
    ])

    //或者在node.js脚本中加上
    db.collection('inventory').insertMany([ ... ]).then((result) => { //...})

    最后,使用find()查询,并打印结构:

    //在client.collect()的callback块内
    var cursor = db.collection('inventory').find({
        // size: { h: 14, w: 21, uom: "cm" }
        // "size.uom": "in"    //使用嵌套的查询
         "size.h": { $lt: 15 }   // 使用条件查询, $lt,代表小于
    })
    
    cursor.toArray((error, documents) => {
      documents.forEach((item) => {
        console.log(item)
      })
    })
    client.close()   //最后关闭db,和连接。

    除使用toArray方法,也可以使用

    forEach(iterator, endcallback)方法:

    参数:

    第一个是:iteratorCallback(doc)

    第二个是:  endCallback(error)

    forEach不提供返回的回调函数。

    ⚠️,Node.js driver中的方法的参数的名字必须和文档上一样!

    cursor.forEach(iterateFunc, errorFunc)
    
    function iterateFunc(doc) {
       console.log(JSON.stringify(doc, null, 4));
    }
    
    function errorFunc(error) {
       console.log(error);
    }

    执行:

    node driver3-query-many.js

    Read Data with Compound Queries

    1. 使用暗示的and查询, 和小于less than符号$lt

    下面的例子取回所有inventory collection内的文档,条件是status 等于"A", 并且qty小于30

    var cursor = db.collection('inventory').find({
      status: "A",
      qty: { $lt: 30}
    })

    暗示的and,其实就是一个逗号 “,” (明确的写法

    小于less than:  $lt  {field: {$lt: value} }

    大于greater than: $gt 

     

    2 使用or查询: $or

    下面的例子取回所有inventory collection内的文档,条件是status 等于"A", 或者qty小于30

    var cursor = db.collection('inventory').find({
      $or: [{status: "A"}, {qty: {$lt: 30}}]
    })

    使用多个组合条件,取回Data

    1。使用暗示的and查询,和一个or分句clause

    下面的例子,取回的document的筛选条件是:

    第一个条件:status等于“A”,

    第二个条件:它的qty必须小于30或者item的第一个字母是"p"

    var cursor = db.collection('inventory').find({ 
      status: "A",
      $or: [ { qty: { $lt: 30 } }, { item: { $regex: "^p" } } ]
    });

    注意⚠️MongoDB支持正则表达式。

    $regex符号,是正则表达式,

      

    Logical Query Operators

     除了上面的案例提到的$and, $or

     还有

    • $not: 例子de.inventory.find( { price: { $not : { $gt: 1.99 }}}), 意思是找到小于或等于1.99的doc。
    • $nor: 关于an array of one or more query expression, 选择的文档要求所有的query表达式都fail!

    ⚠️

    $not符号,需要与其他符号一起使用才行。

    $not符号,不能和$regex一起使用,但可以与/ /一起使用,例子:

    db.inventory.find({item: { $not: /^p.*/}})

    $nor例子:

    db.inventory.find( { $nor: [ { price: 1.99 }, { sale: true } ]  } )

    上面的例子,返回的有4种可能,文档:

    • 包含price字段的值不等于1.99,并且sale的值不等于true
    • 包含price字段的值不等于1.99,但是sale字段不存在于这个document
    • 内没有price字段, 但是包含sale字段,并且sale的值不等于true
    • 内没有price字段,也没有sale字段。

    Comparison Query Operators

    $eq相等符号,一般都被省略

    $gt:  greater than,

    $gte: greater than or equal

    $in:  一个field的值是在in内的任意一个值。

    { field: { $in: [<value1>, <value2>, ... <valueN> ] } }

    $lt: less than

    $lte: less than or equal

    $ne: not equal

    $nin: not in

    $regex: regualr expression.

    { <field>: { $regex: /pattern/, $options: '<options>' } }
    { <field>: { $regex: 'pattern', $options: '<options>' } }
    { <field>: { $regex: /pattern/<options> } }
    //或者使用:
    { <field>: /pattern/<options> }

    Update Data in MongoDB

    MongoDB shell

    MongoDb提供update操作符号来修改值。

    一些update操作符号,如果filed不存在,会创建这个filed。

    下面的操作符号更新第一个符合条件document 。这个操作符号使用:

    • $set: 更新要修改的值。
    • $currentDate: 设置lastModified字段的值为当前时间data
    db.inventory.updateOne(
      { "item" : "paper"},  //查询条件,找到要更新的documents
      {
         $set: { "size.uom" : "cm", "status" : "P"},
         $currentDate: { "lastModified": true} 
      }
    )

    例子:因为'lastModified'不存在,所以新建了这个字段。

    > db.inventory.findOne({"qty": { $lt: 50}})
    { "_id" : ObjectId("5c3dcb30b5986e67b555931d"), "item" : "journal", "qty" : 25, "status" : "A", "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
    
    //使用updateOne后
    > db.inventory.findOne({"qty": { $lt: 50}})
    {
        "_id" : ObjectId("5c3dcb30b5986e67b555931d"),
        "item" : "journal",
        "qty" : 25,
        "status" : "P",
        "size" : {
            "h" : 14,
            "w" : 21,
            "uom" : "cm"
        },
        "tags" : [
            "blank",
            "red"
        ],
        "lastModified" : ISODate("2019-01-17T01:54:47.720Z")
    }

    Node.js driver

    区别是updateOne()如果不提供一个回调函数,会返回一个promise。因此可以连接then()。

    promise和回调函数内的参数当然是一样的。promise是对回调函数的替代。

    const MongoClient = require('mongodb').MongoClient
    const dbHost = '127.0.0.1'
    const dbPort = 27017
    const assert = require('assert')
    
    const url = `mongodb://${dbHost}:${dbPort}`
    
    const dbName = "test"
    
    MongoClient.connect(url, function(error, client) {
      assert.equal(null, error)
      console.log("Connected correctly to server")
    
      const db = client.db(dbName)
    
      db.collection('inventory').updateOne(
        {item: 'paper'},
        {
          $set: {"size.uom": "cm", status: "p"},
          $currentDate: { lastModified: true}
        },
      )
      .then((result) => {
        console.log(result.message)
      })
      client.close()
    })

    collection(name, callback)->{Collection}

    从数据库实例中取一个指定的collection。

    参数callback:类型是collectionResultCallback(error, collection)

    • collection是取回的collection实例。

    updateOne(filter, update, options, callback) -> {Promise}

    在一个collection内,更新一个单一的document。

    参数callback:类型是updateWriteOpCallback(error, result)


    Delete Data from MongoDB

    Mongo Shell

    >ps -e | grep 'mongod'
    
    //mongo mongodb://$[hostlist]/$[database]?authSource=$[authSource] --username $[username]
    >mongo 
    >use test
    >db.inventory.deleteOne(
        { "status": "D" } // specifies the document to delete
    )
    //提示:{ "acknowledged" : true, "deletedCount" : 1 }

    多个删除使用deleteMany

     

    Node.js

    db.collection('inventory').deleteOne({ 
      status: "D" 
    })
    .then(function(result) {
      // process result
    })

    可以使用result.deletedCount得到删除的数量。

    注意remove方法已经被抛弃了。


    Import Data into MongoDB

    mongoimport是一个组件。位于MongoDB 仓库的/bin目录

    下载数据,保存为inventory.crud.json file 

    本地lcoal:

    默认, mongoimport将进口数据到一个MongoDB实例,这个实例位于localhost., port27017。

    如果想要进口数据到一个MongoDb实例,这个实例运行在不同的host or port,

    • 使用 --file option 匹配文件的地址和名字
    • 加上--host and --port options.
    • 使用 --drop option, 如果collection已经存在,会去掉这个collection,从新引入。
    mongoimport --db test --collection inventory 
           --authenticationDatabase admin --username <user> --password <password> 
           --drop --file ~/Downloads/inventory.crud.json

    例子:在terminal

    ⮀ mongoimport --db test --collection inventory --drop --file ~/Downloads/inventory.crud.json
    2019-01-17T19:50:04.185+0800    connected to: localhost
    2019-01-17T19:50:04.185+0800    dropping: test.inventory
    2019-01-17T19:50:05.747+0800    imported 5 documents
  • 相关阅读:
    C# 各版本的新特性
    EntityFramework增删改查
    web.config配置文件中的configSource属性
    IOC
    权限系统设计实现
    代码依赖和解除具体依赖的技术
    ajax利用html5新特性带进度条上传文件
    React Native 从入门到原理
    npm中本地安装命令行类型的模块是不注册Path的
    需求分析-验证控件的功能需求列表
  • 原文地址:https://www.cnblogs.com/chentianwei/p/10274192.html
Copyright © 2011-2022 走看看