zoukankan      html  css  js  c++  java
  • MongoDB基础

    一、mac安装MongoDB

    1.使用homebrew安装

    1. 安装homebrew
    2. 使用brew安装MongoDB

    brew install mongodb

    1. 新建一个目录

    mkdir data

    1. 命令行中指定数据库路径

    mongod --dbpath="./data"

    1. 出现waiting for connections on port 27017就表示启动成功

    2.下载安装包安装

    1. 去官网下载对应的版本

    https://www.mongodb.com/download-center/community?jmp=nav

    1. 解压后放入/usr/local目录下
    2. 配置环境变量

    export PATH=${PATH}:/usr/local/MongoDB/bin

    1. source .bash_profile使配置生效。输入mongod -version,回车后如果看到下面的版本号则说明MongoDB已经成功安装到了Mac上
    2. 新建data文件夹,再建db文件夹。

    sudo mkdir -p /data/db

    mongod启动命令参数

    • --port:指定服务端口号:默认为27017
    • --logpath:指定日志文件(不是目录)
    • --logappend:使用追加的方式写日志
    • --dbpath:指定数据库路径
    • --directoryperdb:设置每个数据库被保存在一个单独的目录
      启动客户端

    mongo

    二、MongoDB基本概念

    1. 数据库:MongoDB单个实例可以容纳多个数据库。

    admin(权限) 要是将用户添加到这个数据库,这个用户自动继承所有数据库的权限。
    local用于存储限于本地单台服务器的任意集合
    config分片设置时,用于保存分片的相关信息。

    1. 集合:数据库由集合组成,类似于关系型数据库中的表
    2. 文档:集合组成文档,文档是一组键值对。

    注:1.文档中的键值对是有序的。2.区分类型和大小写。3.文档不能有重复的键。

    三、MongoDB常见的数据类型

    数据类型 描述
    String 字符串。在MongoDB中,UTF-8才是合法的
    Integer 整型数值。可分为32位或64位
    Boolean 布尔值
    Double 双精度
    Min/Max 将一根值与二进制JSON元素的最低值和最高值对比
    Array 用于将数组或列表的多个值村委一个键
    Timestamp 时间戳
    Object 用于内嵌文档
    Null 用于创建空值
    Symbol 用于采用特殊符号类型的语言
    Date 日期时间
    Object ID 对戏ID
    Binary Data 二进制数据
    Code 文档中存储JavaScript代码
    Regular expression 存储正则表达式

    四、数据库操作

    1. 查看所有数据库:show dbs
    2. 选择数据库:use test

    返回 switched to db test
    注:当选择的数据库未创建,也可以切换过来,但是无法查到,需要在数据库中插入数据才算创建完毕。

    1. 查看当前数据库:dbdb.getName()
    2. 删除数据库:db.dropDatabase()

    返回 {"dropped":"test","ok":1}

    五、集合操作

    1. 查看集合帮助:db.test.help()
    2. 查看数据库下的集合:show collections
    3. 创建一个空集合:db.createCollection(collection_Name)

    db.createCollection(movies)返回{"ok":1}

    1. 创建集合并插入一个文档:db.collection_Name.insert(movies)

    db.douban.insert({name:'阿丽塔'}) 返回
    WriteResult({ "nInserted" : 1 })

    5.删除集合:db.Collection_name.drop()
    5.创建一个有上限的集合:db.createCollection("name",{capped:true,size:10})
    capped:默认值为false表示不设置上限,true表示设置上限

    六、文档操作

    1.插入文档

    1. insert

    db.collection_name.insert(document)
    注:每插入一个文档,默认会生成一个_id属性,用来作为文档的唯一标识,可以直接指定,但是如果集合中已经有了_id的话,会插入失败。

    1. save

    db.collection_name.save(document)
    注:不指定_id字段就类似于insert()方法,如果指定了则会更新该_id的数据。(存在则更新,不存在则添加)

    2.更新文档

    说明

    db.collection.update(
        <query>,
        <updateObj>,
        {
        upsert:<boolean>,
        multi:<boolean>
        }
    )
    
    • query(必选) 查询条件,指定要更新的文档所符合的条件
    • update(必选) 更新后的对象或指定一些更新操作符

    $set直接指定更新后的值
    $inc在原基础上累加

    • upsert(可选),如果不存在符合条件是否插入,默认false不插入
    • multi(可选),MongoDB默认只更新找到的第一条,设置为true,就更新所有符合条件的。必须和$操作符一起才有效。

    简单例子:

    update aritcle set title = "mongodb" where read > 100
    
    db.article.update({"read"{"&gt":100}},{"$set":{"title":"mongodb"}})
    

    操作符

    1. $inc:在原基础上累加

    db.grade1.update({name:"tom"},{$inc:{age:10}}) //tom age 累加10

    1. $push:向数组中添加元素,不会覆盖已有的

    db.grade1.update({name:"tom"},{$push:{"hobby":reading}})

    1. $addToSet:给数组添加或设置一个值

    db.grade1.update({_id:3},{$addToSet:{friends:'huge'}})

    1. $pop:删除数组的第一个或者最后一个元素

    传入1删除最后一个,-1删除第一个
    db.grade1.update({_id:3},{$pop:{friends:1}})

    1. $each:在$addToSet中使用时,若有则忽略,若没有则添加。在$push中使用时,不管有没有都会添加。
    2. $ne:不等于

    db.grade1.update({hobby:{$ne:"reading"}},{$push:{hobby:"drinking"}})

    1. $set:设置字段的值
    
    /*原来的数据*/:
    {_id:3, info:{id: '11'}, friends:['liudehua', 'zhourunfa']}
    
    /*设置字段第一层的值*/
    db.grade1.update({_id:3},{$set:{"info11":{id:"11"}}})
    
    /*设置嵌套字段的值*/
    db.grade1.update({_id:3}, {$set:{"info.id":'22'}})
    
    /*修改指定索引元素*/
    db.grade1.update({_id:3}, {$set:{"friends.1":'zhangmanyu'}})
    
    1. $unset:删除指定的键

    db.grade1.update({name:tom},{$unset:{"age":""}})

    3.删除文档

    db.collection.remove(
        <query>,
        {
          justOne:<boolean>
        }
    )
    
    • query:(可选)删除文档的条件
    • justOne:(可选)设为true或1,则只删除匹配到的多个文档中的第一个。默认为false删除全部

    db.grade1.remove({"name":"tom"},{justOne:treu})
    db.grade1.remove({"name":"tom"}) //删除全部匹配的文档

    4.查询文档

    1. find()

    db.collection_name.find(query,projection);
    query:过滤器,条件
    projection:指定匹配返回哪些键

    /projection/
    { field1: , field2: ... }
    1 or true: 在返回的文档中包含这个字段
    0 or false:在返回的文档中排除这个字段
    注:_id字段默认一直返回,除非手动将_id字段设置为0或false

    db.grade1.find() //查询grade1下的所有文档
    select * from grade1
    
    db.grade1.find({},{"name":1,"age":1})
    
    1. findOne()

    只返回匹配到的第一条文档

    3.方法pretty():将结果格式化

    db.集合名称.find({条件文档}).pretty()

    查询操作符

    1. $in:在数组范围内
    db.grade1.find({age:{$in:[9,11]}})
    select * from grade1 where age in(9,11)
    
    1. $nin:不在数组范围内
    2. $not:取反,为元语句,可以用在任何条件之上
      4.$gt:大于
      5.$gte:大于等于
      6.$lt:小于
      7.$lte:小于等于
      8.$ne:不等于

    数组查询

    原始数据

    { "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }

    db.grade1.find({"friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ]}) //只能查到一条
    db.grade1.find({"friends" : [ "Lily" ]}) //返回空
    db.grade1.find({"friends" :{$all: ["Lily","Zhang San"]}}) //$all 多个元素同时存在才能匹配成功
    db.grade1.find({"friends" :{$in: ["Zhang San"]}}) //$in 范围查询
    db.grade1.find({"friends" :{$size:4}}) //限制数组长度,只有为4才匹配
    db.collection.find( { field: value }, { array: {$slice: count } } ); //当$slice的参数是一个时,表示返回的数量;当是一个数组时,第一个参数表示偏移量,第二个表示返回的数量。

    通过_id查询

    注:通过_id进行查询,需要加上ObjectId

    db.grade1.find({_id: '5c91ed1bcc5f270bc6111d2c'}).count() //0
    db.grate1.find(_id:ObjectId("5c91ed1bcc5f270bc6111d2c")).count()
    //1

    正则匹配

    db.collection.find({key:/value/})

    db.grade1.find({name:/^T/})

    db.grade1.find({name:{$regex:"^zh"}})

    and、or

    and:

    db.grade1.find({field1:value1,field2:value2})

    or:

    db.grade1.find($or:[{key1:value1},{key2,value2}])

    and和or联用

    db.grade1.find({age:9,$or:[{name:tom1},{age:11}]})

    分页查询

    1.limit:控制返回数量

    db.collection_name.find().limit(number)

    2.skip:略过指定数量的数据

    db.collection_name.find().skip(number)

    3.sort:排序,使用 1 和 -1 来指定排序的方式,1为升序排列,而-1用于降序排列。

    4.distinct:去重

    db.collection_name.distinct(‘去重字段’,{条件})

    数据的备份与恢复

    mongodump -h dbhost -d dbname -0 dbdirectory

    -h:服务器地址,端口号
    -d:需要备份的数据库名称
    -o:备份的数据存放位置

    mongorestore -h dbhost -d dbname --dir dbdirectory

    -h:服务器地址,端口号
    -d:需要恢复的数据库实例
    --dir:备份数据所在位置

    聚合aggregate

    聚合是基于数据处理的聚合管道,每个文档通过一个由多个阶段组成的管道,可以对每个阶段的管道进行分组、过滤等操作。然后经过处理再输出相应的结果。

    db.集合名称.aggregate({管道:{表达式}})

    常用管道如下(有些前面已经介绍过):

    1. $group:将集合中的文档分组,可用于统计结果
    2. $match:过滤数据,只输出符合条件的文档
    3. $project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
    4. $sort:将输入文档排序后输出
    5. $limit:限制聚合管道返回的文档数
    6. $skip:跳过指定的文档数,返回余下文档
    7. $unwind:将数组类型的字段进行拆分

    常用表达式:(语法:表达式:$列名)

    1. $sum:计算总和,$sum:1表示以一倍计数
    2. $avg:计算平均值
    3. $min:获取最小值
    4. $max:获取最大值
    5. $push:在结果文档中插入值到一个数组中
    6. $first:更加排序获取第一个文档的数据
    7. $last:根据怕徐获取最后一个文档的数据

    例子:

    # 按性别分组的人数
    db.stu.aggregate(
        {$group:{_id:"$gender",count:{$sum:1}}
    )
    # 按hometown进行分组,获取不同组的平均年龄
    db.stu.aggregate(
        {$group:{_id:"$hometown",mean_age:{$avg:"$age"}}}
    )
    # 将集合中所有文档分为一组  _id为null
    db.stu.aggregate(
        {$group:{_id:null,counter:{$sum:1}}}
    )
    

    注:分组依据放 _id 后面
    取不同的字段需要使用$
    取字典嵌套的字典中的值时用$_id.country
    可以按多个建同时进行分组
    使用$group统计整个文档

    db.stu.aggregate(
        {$group:{_id:null,count:{$sum:1}}}
    )
    

    使用$project

    db.stu.aggregate(
        {$group:{_id:"$gender",count:{$sum:1}},
        {$project:{gender:"$_id",count:1,_id:0}}
    )
    # 修改输入输出的值
    

    使用$match

    #年龄大于20的学生,男性、女性有多少人
    db.stu.agregate(
        {$match:{age:{$gt:20}}},
        {$group:{_id:"$gender",count:{$sum}}},
        {$project:{_id:0,gender:$_id,count:1}}
    )
    # 上一步的结果作为下一步的输入
    
    
    db.stu.aggregate(
        {$group:{_id:{country:$country,province:$province}}},
        {$group:{_id:{country:"$_id.country",province:"$_id.province"}}},
        {$project:{country:"$_id.country",province:"$_id.province",_id:0}}
    )
    

    $unwind的使用

    # 先插入数据
    db.t1.insert([
        {"_id":1,"item":"a","size":["s","m","l"]},
        {"_id":2,"item":"b","size":[]},
        {"_id":3,"item":"c","size":["m"]},
        {"_id":4,"item":"d"},
        {"_id":5,"item":"e","size":null}]
    )
    #使用$unwind将数组字段进行拆分
    db.t1.aggregate({$unwind:"$size"}) //null 不显示
    db.t1.aggregate( [
       { $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }
    ] ) //保留属性值为空的文档
    

    索引

    建立索引:

    db.集合.ensureIndex({属性:1}),1表示升序,-1表示降序

    例子:

    # 先在集合中插入数据作为测试
    for(i=1;i<1000000;i++){db.t1.insert({name:"test"+i,age:i})}
    
    # 查询性能分析
    db.t1.find({name:"test100000"}).explain("executionStats")
    
    # 建立索引
    db.t1.ensureIndex({name:1})
    # 默认_id为索引,上面语句会新建一个索引。再次查询会发现查询速度变快了
    
    # 查看当前集合的所有索引
    db.t1.getIndexes()
    
    # 删除索引
    db.t1.dropIndex("索引名称":1)
    
    # 创建唯一索引
    # 根据关键字段建立 唯一索引,可以对数据进行去重
    db.t1.ensureIndex({name:1},{unique:true})
    
    # 建立联合索引
    db.t1.ensureIndex({name:1,age:1})
    
    

    爬虫数据去重(增量式爬虫):

    1. 根据url地址进行去重(url地址唯一,对应的数据不会改变)

    判断url地址是否在redis的集合中,存在就是请求过,不再请求
    不存在,请求并将url存入redis集合中。

    1. 根据数据本身进行去重

    选择特定的字段,使用加密算法(md5,sha1)将字段进行加密,生成字符串
    新的数据进行相同的加密,如果相同,则看情况更新。不存在,直接插入。

    布隆过滤器:

    使用多个加密算法加密url地址,得到多个值。
    将对应值的位置设置为1
    新的url地址通过算法也生成多个值
    如果对应位置全为1,说明被抓过,否则就将对应位置值设为1

    详细的请参考:
    布隆过滤器1
    布隆过滤器2

    参考:
    https://www.runoob.com/mongodb/mongodb-remove.html
    http://ghmagical.com/article/page/id/Bj7qgmJ3CJUE

  • 相关阅读:
    阿里云:面向5G时代的物联网无线连接服务
    走近科学,探究阿里闲鱼团队通过数据提升Flutter体验的真相
    Redis 5.0新功能介绍
    阿里云发布 Redis 5.0 缓存服务:全新 Stream 数据类型带来不一样缓存体验
    荣获“5G MEC优秀商用案例奖”,阿里云边缘计算发力新零售
    阿里云亮相2019联通合作伙伴大会,边缘计算等3款云产品助力5G时代产业数字化转型
    noip2014 寻找道路
    noip2014 无线网络发射器选址
    noip2014 联合权值
    noip2013 华容道
  • 原文地址:https://www.cnblogs.com/mangM/p/11265907.html
Copyright © 2011-2022 走看看