MongoDB高级操作(上)

-----------------------------------------MongoDB关系------------------------------------

MongoDB的关系表示多个文档之间在逻辑上的相互联系。

文档之间可以通过嵌入引用来建立联系。、

MongoDB中的关系:1:1     1:N     N:1     N:N

实例:1:N 一个用户可以有多个地址

user文档结构:

{
    name:'hedanning',
    contact:"123456789",
    birthday:"1996_01-01"
}

address文档结构:

{
    code:"code_1",
    city:"shanxi"
}

嵌入式关系:

可以把用户地址嵌入到用户文档中:

{
    name:'hedanning',
    contact:"123456789",
    birthday:"1996_01-01",
    address:[
    {
        code:"code_1",
        city:"shanxi"
    },
    {
        code:"code_2",
        city:"beijing"
    }]
}

将user和address的信息都存放在单一的文档中,获取和维护数据比较容易:

查询:db.user.findOne({name:"hdn"},{address:1})

缺点:如果用户和用户地址不断增加,数据量不断变大,会影响读写性能。

引用式关系:

把用户数据文档和用户地址数据文档分开,通过引用文档的id字段来建立关系

{
    name:'HDN',
    contact:"123456789",
    birthday:"1996_01-01",
    address_ids:[
    ObjectId("5d5b90bd03891dd27695ffe5"),
    ObjectId("5d5b90cb03891dd27695ffe6")
]}

         用户文档的address_ids字段包含用户地址的对象id数据。

         我们可以读取这些用户地址的对象id来获取用户的详细地址信息。

查询:这种方法需要两次查询,第一次查询用户地址的对象id,第二次通过查询到的id获取用户的详细地址信息。

  • 使用findOne(),查询符合条件的第一个

       var result = db.user.findOne({name:"HDN"},{address_ids:1})

       db.address.find({"_id":{"$in":result["address_ids"]}})

  • 使用find(),返回的是一个数组

       var result = db.user.find({name:"HDN"},{address_ids:1}).pretty()

       db.address.find({_id:{"$in":result[0]["address_ids"]}})

---------------------------------------MongoDB 数据库引用--------------------------

MongoDB引用有两种:手动引用 和 DBRefs

手动引用:例子同MongoDB关系里面的实例

DBRefs:{$ref:value,$id:value,$db:value}

参数说明

  • $ref:集合名称
  • $id:引用的id
  • $db:数据库名称,可选参数

实例:

address_home集合:

{
    code:"code_home_1",
    city:"shanxi"
}

user集合:

{
    address:{
        $ref:'address_home',
        $id:ObjectId('5d5ba2605c2b17268b794fc1'),
        $db:'test'
    },
    name:'HEHE',
    contact:'123456789',
    birthdat:'19960101'
}

查询:通过指定$ref参数(address_home集合)来查找集合中指定id的用户地址信息:

-----------------------------------------MongoDB覆盖索引查询------------------------------------

覆盖查询是符合以下的查询:

  • 所有的查询字段式索引的一部分
  • 所有的查询返回字段在同一个索引中

由于所有出现在查询中的字段式索引的一部分,MongoDB无需在个数据文档中检索匹配查询条件和返回使用相同索引的查询结果。

从索引中获取数据比通过扫描文档读取数据要快得多。

  • 使用如下的user集合:

{ "_id" : ObjectId("5d5ba99c5c2b17268b794fc3"), "name" : "hdn_1", "age" : 18, "likes" : 100 }
{ "_id" : ObjectId("5d5ba9d55c2b17268b794fc4"), "name" : "hdn_1", "age" : 18, "sex" : "W", "likes" : 100 }
{ "_id" : ObjectId("5d5ba9db5c2b17268b794fc5"), "name" : "hdn_2", "age" : 18, "sex" : "W", "likes" : 100 }
{ "_id" : ObjectId("5d5ba9df5c2b17268b794fc6"), "name" : "hdn_3", "age" : 18, "sex" : "W", "likes" : 100 }
{ "_id" : ObjectId("5d5ba9eb5c2b17268b794fc7"), "name" : "hdn_4", "age" : 19, "sex" : "W", "likes" : 101 }
{ "_id" : ObjectId("5d5ba9f55c2b17268b794fc8"), "name" : "hdn_5", "age" : 20, "sex" : "W", "likes" : 111 }
{ "_id" : ObjectId("5d5baa015c2b17268b794fc9"), "name" : "zl_5", "age" : 20, "sex" : "M", "likes" : 111 }
{ "_id" : ObjectId("5d5baa115c2b17268b794fca"), "name" : "zl_4", "age" : 20, "sex" : "M", "likes" : 11 }
{ "_id" : ObjectId("5d5baa1d5c2b17268b794fcb"), "name" : "zl_3", "age" : 20, "sex" : "M", "likes" : 110 }
{ "_id" : ObjectId("5d5baa255c2b17268b794fcc"), "name" : "zl_2", "age" : 20, "sex" : "M", "likes" : 90 }
{ "_id" : ObjectId("5d5baa2d5c2b17268b794fcd"), "name" : "zl_1", "age" : 20, "sex" : "M", "likes" : 1 }

  • 在user集合中创建联合索引,字段为name和sex:

       db.user.ensureIndex({name:1,sex:1})

  • 查询:db.user.find({sex:'W'},{name:1,_id:0})

       对于以上查询,MongoDB不会user数据库文档中去查找。相反,它会从索引中提取数据,这是非常快速的数据查询。

       由于我们的索引中不包含_id字段,_id在查询中会默认返回,我们可以在MongoDB的查询结果集中排除它,这样才会索引覆盖查询。

换句话说:查询条件是索引的一部分,返回字段也是索引的一部分,这样称为索引覆盖查询。

-----------------------------------------MongoDB查询分析------------------------------------

MongoDB查询分析可以确保我们所建立的索引是否有效,是查询语句性能分析的重要工具。

MongoDB查询分析常用的函数有:explain()和hint()。

explain():提供查询信息,使用索引及查询统计等,有利于对索引优化。

在------------MongoDB覆盖索引查询------------章节已经建立索引的基础之上进行以下操作:

db.user.find({sex:'W'},{name:1,_id:0}).explain()

hint():使用hint()来强制MongoDB使用一个指定的索引。

例子: db.user.find({sex:'W'},{name:1,_id:0}).hint({name:1,sex:1})

使用explain()函数分析以上查询:db.user.find({sex:'W'},{name:1,_id:0}).hint({name:1,sex:1}).explain()

-----------------------------------------MongoDB原子操作:findAndModify()------------------------------------

注意:MongoDB不支持事务,也就是MongoDB不能保证数据的完整性。

但是MongoDB提供了许多原子操作,比如文档的保存,修改,删除等,这些都是原子操作。

所谓的原子操作就是要么这个文档保存到MongoDB,要么没有保存到MongoDB,不会出现查询到的文档没有保存完整的情况。

原子操作数据模型

{
    title:'MongoDB教程',
    checkout:[{
        by:'hdn',
        date:new Date()
       }]
}

使用findAndModify()方法在一个文档中确保多个字段同步更新。

db.book.findAndModify({
    query:{
        title:'MongoDB教程'
        },
    update:{
        $set:{title:'MongoDB学习'},
        $push:{checkout:{by:'hedanning',date:new Date()}}
        }
})

原子操作常用命令:

  • $set:用来指定一个键并更新键值,若键不存在就创建 —— { $set : { field : value } }
db.book.findAndModify({
    query:{
        title:'MongoDB学习'
    },
    update:{
        $set:{price:99.99}
    }
})

  • $unset:用来删除一个键 —— { $unset : { field : 1} }

       将price删除

db.book.findAndModify({
    query:{
            title:'MongoDB学习'
           },
    update:{
            $unset:{price:1}
            }
})

  • inc:可以对文档的某个数字类型值的键进行增减的操作 —— { $inc : { field : value } }

db.book.findAndModify({
    query:{
            title:'MongoDB学习'
        },
    update:{
            $inc:{price:1}
        }
})

  • push:把value追加到field里面去,field一定要是数组类型,如果field不存在,会新增一个数组类型加进去 —— 

         { $push : { field : value } }

db.book.findAndModify({
    query:{
            title:'MongoDB学习'
        },
    update:{
            $push:{author:{name:'AAA',city:'china'}}
        }
})

  • $pull:从数组field内删除一个等于value值 —— { $pull : { field : _value } }
db.book.findAndModify({
    query:{
        title:'MongoDB学习'
    },
    update:{
        $pull:{checkout:{by:'hdn'}}
    }
})

  • $addToSet:增加一个值到数组内,而且只有当这个值不在数组内才增加。否则,不会增加 —— {$addToSet:{key:value}}

区别:$push和$addToSet的区别?

$push:不论要添加的值数组中是否存在,始终都会进行添加。

$addToSet:只有当数组中不存在将要添加的值,该值才会添加到数组中,否则,不进行添加。

  • $pop:删除数组中的第一个值和最后一个值。

       删除最后一个元素:{$pop:{field:1}}           删除第一个元素:{$pop:{field:-1}}

  • $rename:修改字段名称 —— {$bit : { field : {and : 5}}}
 db.book.findAndModify({
    query:{
            title:'MongoDB学习'
        },
    update:{
            $rename:{email:'Email'}
        }
})

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MongoDB是一个流行的NoSQL数据库,提供了许多高级操作来处理和管理数据。以下是一些MongoDB高级操作: 1. 聚合操作MongoDB的聚合操作可以对集合中的文档进行复杂的数据处理和分析。它包括管道操作符,可以进行排序、筛选、分组、映射、限制和计算等操作,以生成所需的结果。 2. 索引优化:索引是MongoDB中优化查询性能的重要工具。通过为经常查询的字段创建索引,可以加快查询速度。MongoDB支持多种类型的索引,如单字段索引、组合索引、文本索引和地理空间索引等。 3. 事务处理:MongoDB从版本4.0开始支持事务处理。事务是一组关联操作的集合,要么全部成功执行,要么全部失败回滚。事务处理可确保在并发环境下数据的一致性和完整性。 4. 数据备份和恢复:MongoDB提供了多种备份和恢复数据的方式。可以使用mongodump和mongorestore命令行工具进行全量备份和恢复,也可以使用Oplog来进行增量备份和恢复。 5. 数据迁移:当需要将数据从一个MongoDB实例迁移到另一个实例时,可以使用mongodump和mongorestore命令行工具来执行全量数据迁移。同时,还可以使用MongoDB的复制集和分片集群功能来实现数据的高可用和水平扩展。 6. 数据加密:MongoDB提供了字段级别的数据加密功能。可以使用客户端端到端加密的方式来保护敏感数据,确保数据在存储和传输过程中的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值