阅读 250

mongoDB 增删改查

基本概念

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。MongoDB中的记录是一个文档,它是由字段和值对组成的数据结构。文档类似于JSON对象,存储在集合中。集合类似于关系数据库中的表。

MongoDB 将数据记录存储为 BSON 文档。BSON 是JSON文档的二进制表示,但它包含的数据类型比 JSON 多

image.png

shell 中使用

image.png

创建数据库

use 数据库名

如果数据库不存在,则创建数据库,否则切换到指定数据库。

db.createCollection(集合名称 , 可选参数)

创建集合,可选参数如下:

db.createCollection( <name>,
   {
     capped: <boolean>,
     timeseries: {                  // Added in MongoDB 5.0
        timeField: <string>,        // required for time series collections
        metaField: <string>,
        granularity: <string>
     },
     expireAfterSeconds: <number>,
     autoIndexId: <boolean>,
     size: <number>,
     max: <number>,
     storageEngine: <document>,
     validator: <document>,
     validationLevel: <string>,
     validationAction: <string>,
     indexOptionDefaults: <document>,
     viewOn: <string>,              // Added in MongoDB 3.4
     pipeline: <pipeline>,          // Added in MongoDB 3.4
     collation: <document>,         // Added in MongoDB 3.4
     writeConcern: <document>
   }
)
复制代码

image.png

也可以直接在集合中插入相应数据,会自动创建集合,如:db.user.insert({name:'admin'})

仅仅使用 use <数据库名> 切换到对应数据库后 show dbs,并不会找到刚创建的那个数据库,需要向库中添加一些数据之后才能查询到,默认使用的test库。

删除数据库

删除集合(表),如果集合是最后一个被删除后,通过show dbs 也看不到对应的库

db.集合名称.drop()

image.png

删除数据库,切换到指定库中进行相应删除操作

db.dropDatabase()

数据CRUD

ObjectId(<hexadecimal>)

返回一个长度位24的字符串(并不是字符串,实际上是mongo里面特有的一种类型)

  • 一个 4 字节的时间戳值,代表 ObjectId 的创建,以 Unix 纪元以来的秒数为单位
  • 一个 5 字节的随机值
  • 一个 3 字节递增计数器,初始化为随机值

插入时如果该集合当前不存在,则插入操作将创建该集合;存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略了该 _id 字段,MongoDB 驱动程序会自动为该字段生成一个ObjectId_id

数据插入

db.collection.insertOne()

将单个文档插入到集合中

db.user.insertOne({
    name: "test1",
    age: 18,
    grade: 1,
    parents: ["test1P1", "test1P2"],
    description: {
        hobby: "sleep",
        skill: ["sing", "jump", "rap", "basketball"],
        score: 59,
    }
})
复制代码
db.collection.insertMany()

将多个文档插入到一个集合中

db.user.insertMany([
    {
        name: "test1",
        age: 18,
        grade: 1,
        parents: ["test1P1", "test1P2"],
        description: {
            hobby: "sleep",
            skill: ["sing", "jump", "rap", "basketball"],
            score: 59,
        }
    }
])
复制代码
db.collection.insert()

将单个文档或多个文档插入到集合中

db.user.insert({
    name: "test1",
    age: 18,
    grade: 1,
    parents: ["test1P1", "test1P2"],
    description: {
        hobby: "sleep",
        skill: ["sing", "jump", "rap", "basketball"],
        score: 59,
    }
});
db.user.insert([
    {
        name: "test1",
        age: 18,
        parents: ["test1P1", "test1P2"],
        description: {
            hobby: "sleep",
            skill: ["sing", "jump", "rap", "basketball"],
            score: 59,
        }
    }
]);
复制代码

数据删除

db.collection.deleteOne()

最多删除一个与指定过滤器匹配的文档,即使多个文档可能与指定的过滤器匹配

db.user.deleteOne({ "_id": ObjectId("611dc577166b0506cd3d6cb0") })
复制代码
db.collection.deleteMany()

删除与指定过滤器匹配的所有文档

db.user.deleteMany({ age: 18 })
复制代码
db.collection.remove()

删除单个文档或与指定过滤器匹配的所有文档

db.user.remove({ age: 18 });
db.user.remove({});
复制代码

db.user.remove({}) 这个操作不等于 drop() 方法,要从集合中删除所有文档,使用drop()方法删除整个集合(包括索引),然后重新创建集合并重建索引更有效。

数据修改

db.collection.updateOne(<filter>, <update>, <options>)

配合 $set 等操作符来更新单个文档的部分属性

db.user.updateOne({
    _id: ObjectId("611e0083b3e0ed299caa7183")
}, {
    $set: {
        name: 'newName'
    }
})
复制代码
db.collection.updateMany(<filter>, <update>, <options>)

更新与集合的指定过滤器匹配的所有文档

db.user.updateMany({
    grade: 1
}, {
    $set: {
        grade: 2
    }
})
复制代码
db.collection.update(<filter>, <update>, <options>)

配合 $set 等操作符来更新单个或者多个(取决于options里面的 multi 是否为 true,默认为 false)文档的部分属性

db.user.update({
    grade: 1
}, {
    $set: {
        grade: 2
    }
}, {
    multi: true,
})
复制代码
db.collection.replaceOne(<filter>, <update>, <options>)

覆盖式更新,不能只更新某一个字段,用新的文档替换匹配到的那个文档

db.user.replaceOne({
    _id: ObjectId("611e0083b3e0ed299caa7183")
}, {
    name: "newDocument",
    age: 18,
    grade: 1,
    parents: ["test1P1", "test1P2"],
    description: {
        hobby: "sleep",
        skill: ["sing", "jump", "rap", "basketball"],
        score: 59,
    }
})
复制代码

以上几个方法中 <options> 参数中的 upsert 属性如果为 true时(默认为false),此方法在<filter>没有匹配到文档时,会将<update>作为新的文档插入到集合中,如:

db.user.replaceOne({
    _id: ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa")
}, {
    name: "updateForCreate",
    age: 18,
    grade: 1,
    parents: ["test1P1", "test1P2"],
    description: {
        hobby: "sleep",
        skill: ["sing", "jump", "rap", "basketball"],
        score: 59,
    }
}, {
    upsert: true
})
复制代码

数据查询

db.collection.find(<filter>)

基于以下5条数据做查询操作

db.user.insertMany([
    {
        "name": "a",
        "age": 18,
        "grade": 1,
        "parents": [
            "aP1",
            "aP2"
        ],
        "hobby": "coffee-shop-cake",
        "description": {
            "skill": [
                "sing"
            ],
            "score": 88
        }
    },
    {
        "name": "b",
        "age": 18,
        "grade": 1,
        "parents": [
            "aP1",
            "aP2"
        ],
        "hobby": "java-coffee",
        "description": {
            "skill": [
                "jump"
            ],
            "score": 99
        }
    },
    {
        "name": "d",
        "age": 19,
        "grade": 2,
        "parents": [
            "dP1",
            "dP2"
        ],
        "hobby": "eat-run",
        "description": {
            "skill": [
                "basketball"
            ],
            "score": 59
        }
    },
    {
        "name": "c",
        "age": 19,
        "grade": 1,
        "parents": [
            "cP1",
            "cP2"
        ],
        "hobby": "sleep",
        "description": {
            "skill": [
                "rap"
            ],
            "score": 59
        }
    },
    {
        "name": "e",
        "age": 20,
        "grade": 3,
        "parents": [
            "eP1",
            "eP2"
        ],
        "hobby": "sleep-java",
        "description": {
            "skill": [
                "sing",
                "jump",
                "rap",
                "basketball"
            ],
            "score": 69
        }
    }
])
复制代码
查询所有数据
db.user.find();
db.user.find({});
复制代码

image.png

且(&&)查询

查询 grade 等于 1 并且 age 等于 19 的数据:

db.user.find({ grade: 1, age: 19 });
复制代码
db.user.find({ $and: [{ grade: 1 }, { age: 19 }] });
复制代码

image.png

或(||)查询

查询 age 等于 18 或 19 的数据:

db.user.find({ $or: [{ age: 18 }, { age: 19 }] });
复制代码
db.user.find({ age: { $in: [18, 19] } });
复制代码

image.png

模糊查询

在模糊查找之前需要存在索引否则会报text index required for $text query的错误,可以通过

  • db.collection.createIndex( <key and index type specification>, <options> ) 创建索引
  • db.collection.getIndexes() 查询索引
  • db.collection.dropIndex(index) 删除索引
db.user.dropIndex("hobby_text")
db.user.createIndex({ hobby: "text" })
复制代码

创建好索引之后使用$text操作符进行模糊查找,参数格式如下:

{
  $text:
    {
      $search: <string>, 
      $language: <string>,
      $caseSensitive: <boolean>,
      $diacriticSensitive: <boolean>
    }
}
复制代码

查询索引字段里面包含 coffee 的数据:

db.user.find({ $text: { $search: "coffee" } })
复制代码

image.png

比较运算符查询
  • $eq:相等(==)
  • $ne:不等(!=)
  • $gt:大于(>)
  • $lt:小于(<)
  • $gte:大于等于(>=)
  • $lte:小于等于(<=)
  • $in:存在
  • $nin:不存在

查询 age 大于等于 18 小于等于 19,parents 中包括 "aP1" 或 "cP1" 的但是 name 不为 "b" 的数据:

db.user.find({
    $and: [
        { age: { $gte: 18 } },
        { age: { $lte: 19 } },
        { parents: { $in: ["aP1", "cP1"] } },
        { name: { $ne: "b" } }
    ]
})
复制代码

image.png

嵌套查询

查询 description 中 score 大于等于 69 的数据:

db.user.find({ "description.score": { $gte: 69 } })
复制代码

image.png $elemMatch 操作符 匹配包含 数组字段 的文档,其中至少有一个元素与所有指定的查询条件匹配
查询 description 中 skill 中 包含 "jump" 的数据:

db.user.find({ "description.skill": { $elemMatch: { $eq: "jump"  } } })
复制代码

image.png

因为这里 skill 字段是一个字符串数组,也可以使用 $in操作符,更简单

db.user.find({ "description.skill": { $in: ["jump"] } })
复制代码

如果 skill 字段是一个对象数组,需要对对象里面的某个字段在做筛选的话就需要得用 $elemMatch 操作符了,如:

description.skill = [
    {key:"skillA",value:"sing"},
    {key:"skillB",value:"jump"},
    {key:"skillC",value:"rap"},
    {key:"skillD",value:"basketball"},
]
description.skill = [
    {key:"skillA",value:"sing"},
    {key:"skillB",value:"jump"},
]
复制代码
db.user.find({ "description.skill": { $elemMatch: { value: "jump" } } })
复制代码

image.png

$where操作符查询

{ $where: <string|JavaScript Code> }$where运算符将包含 JavaScript 表达式的字符串或完整的 JavaScript 函数传递给查询系统,可以使用this或引用 JavaScript 表达式来操作当前文档。

查询 age = 18 且 description属性中的 score = 88 的数据:

db.user.find({
    $where: function() {
        return (this.age === 18 && this.description.score === 88)
    }
})
复制代码

image.png

排序、分页
  • sort({<field>:1 或 -1}) 1 为升序,-1 为降序
  • limit(<number>) 设定结果集中显示的文档数,等于0时表示所有
  • skip(<number>) 设定结果集中要跳过的文档数

现在共有5条数据,假设分页后每页只有一条数据,查询按照 age 倒叙排序的第3页的数据:

db.user.find().sort({ age: -1 }).skip(2 * 1).limit(1)
复制代码

image.png

文章分类
后端
文章标签