Mongodb

MongoDB

  1. MongoDB是由C++编写的分布式文档数据库
  2. 内部使用类似于json的bson格式
  3. 中文手册:https://www.w3cschool.cn/mongodb/

安装

  1. 下载链接:https://www.mongodb.com/download-center/community
    • windows下载官方zip,解压即可使用
组件文件名
Servermongod.exe
Routermongos.exe, Query Router, Sharding Cluster
Clientmongo.exe
MonitoringToolsmongostat.exe, mongotop.exe
ImportExportToolsmongodump.exe, mongorestore.exe, mongoexport.exe, mongoimport.exe
MiscellaneousToolsbsondump.exe, mongofiles.exe, mongooplog.exe, mongoperf.exe

运行

$ D:
$ cd mongodb4/bin
$ ./mongod.exe 
// 抛exception in initAndListen: NonExistentPath: Data directory D:\data\db\ not found., terminating异常
$ mongod.exe --help
选项选项说明
–bind_ip绑定以逗号分隔的IP地址;默认localhost
–bind_ip_all绑定所有本地IP地址
–port端口,默认27017
–dbpath数据存放的path路径,可以配置;缺省/data/db,windows下缺省盘符://data/db;
–logpath指定日志的path路径,替代stdout,可以配置;缺省是控制台打印日志
–f指定配置文件(yaml格式);可以执行配置文件执行mongod.exe

注册windows服务

  • 选中我的电脑,右击查看管理,选择服务和应用程序
  • 点击服务,查看windows服务
选项选项说明
–install注册windows服务
–serviceName服务名称
–serviceDisplayName服务显示名
  • Windows注册为服务的命令如下(使用了配置文件)
    • $ mongode.exe -f "D://mongodb4//db/mongod.yml" --serviceName mongodb -- serviceDisplayName mongo --install

注意:Windows下可以不注册为服务运行MongoDB,且注册服务需要管理员权限


配置文件

  • MongoDB配置使用YAML格式
    • 嵌套使用缩进完成
    • 冒号后面要有空格
    • **注意:不支持Tab等制表符,支持空格

参考文档

  • Yaml参考:https://www.w3cschool.cn/iqmrhf/dotvpozt.html
  • 配置:http://mongoing.com/docs/reference/configuration-options.html
  • 参考配置,详细参考配置点击Core Options
systemLog: # 设置日志输出路径
   destination: file # 缺省是输出日志到std; file表示输出到文件
   path: "/var/log/mongodb/mongod.log" # 日志文件路径,且文件目录必须存在,文件可以不用存在
   logAppend: true # true,在已存在的日志文件EOF处追加;默认false,每次启动服务,重新创建新的日志文件
storage: # 设置数据存放路径
   journal:
      enabled: true
   dbPath: # 设置数据存放的路径,必须指定mongodb的数据目录,且目录必须存在
      "D://data/db" # 缺省/data/db
processManagement:
   fork: true
net: # 设置MongoDB的ip和port
   bindIp: 127.0.0.1 # 设置MongoDB的ip地址
   port: 27017 # 设置MongoDB的port,缺省27017
setParameter:
   enableLocalhostAuthBypass: false

  • 实际配置
systemLog: # 设置日志输出路径
   destination: file # 缺省输出日志到std,file表示输出到文件
   path: "/var/log/mongodb/mongod.log" # 日志文件路径,文件目录必须存在
   logAppend: true # true,表示在已存在的日志文件中E
storage: 
   dbpath: "D://mongodb/db" # 注意,数据存放的目录必须是db
net: # 设置MongoDB的ip和port
   bindIp: 127.0.0.1
   port: 27017

客户端

Windows客户端连接

  • command(DOS,磁盘操作系统的缩写)中启动MongoDB连接
$ D:
$ cd mongodb4/bin
$ mongd.exe -f D://mongodb/db" 
  • command中启动Client连接
$ mango.exe
help // 打开帮助
show dbs // 查看当前所有库
use blog
// blog库存在,切换;不存在,创建blog库
// 注意:刚创建的库并不在MongoDB数据库列表中,需要写入数据后才能看到

db // 查看当前数据库

db.users.insert({user:"tom", age:20}) 

// db代指数据库,users为Colletions名
// 注意:user、age没有加引号,类似于js的对象

Windows可视化工具

  • Compass
  • 下载地址:https://www.mongodb.com/products/compass

Pycharm插件

  • 在settings/plugins中输入mongo,安装Mongo Plugin,完成后重启Pycharm
  • 菜单项选择 View/Tool Windows/Mongo Explorer

python连接

  • Mongodb官方推荐使用pymongo,参照文档:https://docs.mongodb.com/ecosystem/drivers/pymongo/
  • $ python -m pip install pymongo
    • 缺省安装pymongo 3.10,支持MongoDB2.6+,兼容Python3.4+
    • 可以执行安装、更新,详情查看参照文档

Python连接

  • MongoDB的连接字符串"mongodb://username:password@127.0.0.1:27017/test"
from pymongo import MongoClient
from pymongo.results import InsertOneResult

# 客户端连接
# client = MongoClient(host="127.0.0.1", port="27017")
client = MongoClient("mongodb://127.0.0.1:27017")
print(client) # MongoClient对象,连接到数据库

# 既能属性访问,又能向key一样访问,一定实现了魔术方法__getattr__和__getitem__
# db = client.blog 
db = client["blog"] # 指定数据库,对应RDBMS的DataBase
print(db) # Database对象,库对象

# users = db["users"] 
users = db.users # 指定数据库中的users Collection,对应RDBMS的Table
print(users)


基本概念

  • MongoDB中可以创建使用多个库,但有一些数据库名是保留的,可以直接访问这些特殊作用的数据库
  1. admin:从权限的角度来看,这是"root"数据库
    • 需要将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限;
    • 一些特定的服务端命令也只能从这个数据库运行,比如列出所有的数据库/关闭服务器
  2. local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  3. config:当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息

MongoDb和RDBMS的对应关系

MongoDBRDBMS
DatabaseDatabase
TableCollection
RowDocument
ColumnField
JoinEmbedded Document嵌入文档或Reference引用
Primary Key主键(MongoDB提供了key为_id)

文档

  • 每一条记录对应一个文档,其格式使用BSON。
    • BSON,即Binary JSON

文档

  1. 文档中,使用键值对
  2. 文档中,键值对是有序
    • 字符串,区分大小写,使用UTF-8字符
    • 键不能含有\0(空字符)。这个字符用来表示`键字符串的结尾(C、C++语言中,表示字符串的结尾)
    • .$有特别的意义,只有在特定环境下才能使用
    • 以下划线_开头的键是保留的,例如_id
    • 字符串、32位或64位整数、双精度、时间戳(毫秒)、布尔型、null
    • 字节数组、BSON数组、BSON对象

MonogoDB类型

  1. 类型参考:https://docs.mongodb.com/v3.6/reference/bson-types/
  2. 常用类型:
    • 字符串类型编码为2,别名string
    • 数值整形编码为16,别名int
    • 长整型编码为18,别名long
    • 浮点型编码为1,别名为double

BSON二进制阅读
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1idTGsRF-1578309542614)(D:\1Face_To_Face\爬虫\xmind\BSON.png)]

  • 二进制源码查看对应数据库的db/collection-x-xxx.wt
  • 00 00 05 82 d7 35 00 00 00 07 5f 69 64 00 5d 45
    • 35表示二进制的长度
    • 07表示MongoDB中特殊数据类型ObjectId
    • 5f 69 64,为ASCII的_id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UY7zIQMV-1578309542616)(D:\1Face_To_Face\爬虫\xmind\二进制解读.png)]


插入数据

  • 单条插入insert_one(self, document, bypass_document_validation=False,session=None)
    • document,字典
  • 多条插入insert_many(self, documents, ordered=True,
    bypass_document_validation=False, session=None)
    • documents,多个字典组成的列表
from pymongo import MongoClient
from pymongo.results import InsertOneResult, InsertManyResult
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] 

users:Collection = db.users

user1 = {"id":1, "name":"ben", "age":20}
user2 = {"id":257, "name":"jerry", "age":30}
user3 = {"id":258, "name":"tom", "age":49}
user4 = {"id":3, "name":"shiqi", "age":"50", "NAME":'tommy'} # Mongodb中,大小写敏感,且field可以不用一致

# 单条插入
# users.insert(user1) # 已经弃用
one:InsertOneResult = users.insert_one(user1)
print(type(one)) # InsertOneResult类型
print(one) # InsertOneResult实例对象
print(one.inserted_id) # 查看MongoDB提供的_id值,ObjectId对象

# 多条插入
many:InsertManyResult = users.insert_many([user2, user3])
print(type(many)) # InsertManyResult类型
print(many) # InsertManyResult实例
print(many.inserted_ids) # 返回由多个ObjectId对象组成的列表

# 大小写敏感、field可以不用一致
one:InsertOneResult = users.insert_one(user4)
print(one.inserted_id)

ObjectId

  • 主键,由MongoDB提供了key,field为_id,Collection为ObjectID
  • ObjectID由12个字节组成,每个字节由16进制表示
    1. 4字节时间戳
    2. 3字节机器识别码
    3. 2字节进程ID
    4. 3字节随机数
from pymongo import MongoClient
from pymongo.results import InsertOneResult, InsertManyResult
from pymongo.collection import Collection
import datetime

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

id = "5e0c085b99ce1f32e8393e98"

# 前4个字节为时间戳
stamp = id[:8]
stamp = int.from_bytes(bytes.fromhex(stamp), 'big') # 从十六进制字符串转为字节,再由字节转为int类型,注意大小端

print(hex(stamp), type(stamp))
t = datetime.datetime.fromtimestamp(stamp) # fromtimestamp将浮点数时间戳转为datetime.datetime类型
print(t, type(t))

import bson
print(bson.ObjectId(id).generation_time) # 返回UTC时间,咱们是东八区,比UTC时间快8小时

查询

  • 单值查询:find_one
    • 第一参数为filter
    • 查询有值,返回字典(带_id);未查询到,返回None
  • 多值查询:find
    • 第一参数为Collection实例对象self
    • 第二参数为filter
    • 查询到,返回Cursor对象,可迭代对象;未查询到,返回空
from pymongo import MongoClient
from pymongo.collection import Collection
from bson.objectid import ObjectId

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

# 单值查询
result = users.find_one({"name": "tom"})
print(type(result), result) # 返回查询集,字典

result = users.find_one({'_id': ObjectId('5e0c0766ec444982c52e217d')})
print(type(result), result) # 通过_id查询,返回拆查询集

result = users.find_one({"name": "able"})
print(type(result), result) # 未找到,返回None

# 多值查询
results = users.find() # find什么参数都不写,表示全文搜索
results = users.find({'age': 30}) # 注意:MongDB有数值的概念,所以使用数值
print(type(results)) # Cursot object,可迭代对象
print(results)

for x in results:
    print(type(x), x)

查询操作

  • 比较
比较符号含义示例
$lt小于{"age":{"$lt":20}}
$gt大于{"age":{"$gt":20}}
$lte小于等于{"age":{"$lte":20}}
$gte大于等于{"age":{"$gte":20}}
$ne不等于{"age":{"$ne":20}}
$eq等于,可以不写{"age":{"$eq":20}}
$in在范围内{"age":{"$in":20}}
$nin不在范围内{"age":{"$nin":20}}
  • 逻辑
逻辑符号含义示例
$and{"age":[{"name":"tom"}, {"age":{"$gt":20}}]} {"name":"tom", "age":{"$gt":20}}
$or{"or":[{"name":"tom"}, {"age":{"$gt":20}}]}
$not{'age':{"$not":{"$lte":20}}}
  • 元素
元素符号含义示例
$exists判断文档中是否有这个字段,true表示有此字段,False表示无此字段,且将符合条件的document显示{"name":{"$exists":True}}
$type判断字段是否是指定的类型,将符合条件的document显示{"age":{"$type":16}}
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

users.delete_many({}) # 删除collection中的所有数据

user1 = {"id":1, "name":"ben", "age":20}
user2 = {"id":257, "name":"jerry", "age":30}
user3 = {"id":258, "name":"tom", "age":49}
user4 = {"id":3, "name":"shiqi", "age":"50", "NAME":'tommy'}

users.insert_many([user1, user2, user3, user4])
print(*users.find(),sep='\n')

print(*users.find({"NAME":{"$exists":True}}), sep='\n')
print('~~~~~~~~~~~~~~~~~~~')
print(*users.find({"age":{"$type":2}}),sep='\n')

  • 其他
操作符号含义示例
$regex使用正则表达式,对文档中的内容匹配{"name":{"$regex":"^t"}}
$mod取模,选择符合取模运算的document{"age":{"$mod":[10,2]}},模10余2的document
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

users.delete_many({}) # 删除collection中的所有数据

user1 = {"id":1, "name":"ben", "age":20}
user2 = {"id":257, "name":"jerry", "age":30}
user3 = {"id":258, "name":"tom", "age":49}
user4 = {"id":3, "name":"shiqi", "age":50, "NAME":'tommy'}

users.insert_many([user1, user2, user3, user4])
print(*users.find(),sep='\n')

print('~' * 30)
print(*users.find({"name":{"$regex":"^s"}}), sep='\n')

print('*' * 30)
print(*users.find({"age":{"$mod":[2,1]}}), sep='\n')

投影

Cursor的第二参数projection(投影)

  • 投影保留
    1. 元组/列表:将保留的field构建成元组/列表,作为实参传入find的第二参数
    2. dict:{"保留field": True, "保留field": 1}
  • 投影排除
    • dict: {"排除ield": False, "排除field: 0}

注意:投影字典中,要么全是保留,要么全是排除;同时出现保留和排除,抛pymongo.errors

from pymongo import MongoClient
from pymongo.collection import Collection
from bson.objectid import ObjectId

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

# 保留field
results = users.find(filter={'age':{"$gt":20}},projection=("name", "tom")) 

results = users.find(filter={"name":"shiqi"}, projection={"name":1, "age":True}) # 保留

# 排除field 
results = users.find(filter={"name":"shiqi"}, projection={"name":0, "age":False}) # 排除

# 注意:抛异常
# results = users.find(filter={"name":"shiqi"}, projection={"name":True, "age":False}) # 抛pymongo.errors

for x in results:
    print(x)

统计

  • count_documents(self, filter, session=None, **kwargs)
from pymongo import MongoClient
from pymongo.collection import Collection
from bson.objectid import ObjectId

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

# results = users.find(filter={'age':{"$gt":20}},projection=["name", "aget"]).count() # deprecate,丢弃
print(users.count_documents(filter={"age": {"$gt": 20}}))

排序

  • sort(self, key_or_list, direction=None)
    • self,cursor对象
    • key_ro_list,需要排序的field;多个field排序,使用列表
    • direction,缺省升序;pymongo.ASCEDING控制升序,pymongo.DESCENDING控制降序
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection
from bson.objectid import ObjectId

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

# 升序
results = users.find().sort('age') # 默认升序
results = users.find().sort('age', ASCENDING) # 默认升序

# 降序
results = users.find().sort('age', DESCENDING) # 降序
results = users.find().sort('age', -1) # 降序

for result in results:
    print(result)


分页

  • limit(),限制查询结果数
    • limit()支持负整数,只不过取绝对值,不是取倒数第三个
  • skip(),类似于MySQL中的offset
    • skip()不支持负整数,抛ValueError
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

# 分页
results = users.find()
print(*list(results), sep='\n')
print('-' * 30)

# skip,跳过,类似于mysql中的offset
results = users.find().skip(1) 
print(*list(results), sep='\n')
print('~' * 30)

# limit,限制结果个数
results = users.find().limit(3)
results = users.find().limit(-3) 
print(*list(results), sep='\n')
print('*' * 30)

# 先跳过,后限制,limit和skip的先后循序不影响
# results = users.find().skip(2).limit(-2) #
results = users.find().limit(3).skip(2)
print(*list(results), sep='\n')

更新

更新操作符含义示例
$inc对给定字段的数值进行增减{'$inc':{'age':-5}}
$set设置字段值,如果字段不存在则创建{'$set':{'gender':"M"}
$unset移除字段{"$unset":{"Name":""}}

只更新第一个

  • update_one
    1. 第一参数filter
    2. 第二参数updata,可以使用更新字符串;格式为{"更新字符串”:{"field":"响应操作"}}
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"tom"}
# result = users.update() # 弃用
result = users.update_one(filter, {"$inc":{"age": 5}}) # 找到tom,且age+5
print(users.find_one(filter))

result = users.update_one(filter, {"$inc":{"age": -5}}) # 找到tom.且age-5
print(users.find_one(filter))

  • update_many
    1. 第一参数filter
    2. 第二参数updata,可以使用更新字符串;格式为{"更新字符串”:{"field":"响应操作"}}
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"tom"}
results = users.update_many(filter,{"$set":{"NAME": "Tom"}})
print(*users.find(filter), sep='\n')

替换

  • replace_one
    • 更新除_id字段外的所有字段
    • 更新一个document,即更新一个记录
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"tom"}
users.replace_one(filter, {'id':10, "name":"test", "age": 29})
print(*users.find({"name": "test"}), sep='\n')

删除

删除一个

  • delete_one
    • 第一参数filter
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"test"}
# users.remove() # 弃用
delete_result = users.delete_one(filter)
print(type(delete_result), delete_result.deleted_count) # delted_count,返回删除的document数量
print(delete_result) # pymongo.results.DeleteResult实例对象
print(*users.find(filter), sep='\n')

删除多个

  • delete_many
    • 第一参数filter
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"test"}
delete_results = users.delete_many(filter)
print(type(delete_results), delete_results.deleted_count) # delted_count,返回删除的document数量
print(delete_results) # pymongo.results.DeleteResult实例对象
print(*users.find(filter), sep='\n')

删除所有文档

  • users.delete_many({})
    • 删除collection中的所有数据
    • 慎用

users.find(filter), sep=’\n’)


### 删除多个
* delete_many
    * 第一参数filter

```python
from pymongo import MongoClient, ASCENDING, DESCENDING
from pymongo.collection import Collection

client = MongoClient("mongodb://127.0.0.1:27017")

db = client["blog"] # 切片访问,魔术方法__getitem__实现

users:Collection = db.users

filter = {"name":"test"}
delete_results = users.delete_many(filter)
print(type(delete_results), delete_results.deleted_count) # delted_count,返回删除的document数量
print(delete_results) # pymongo.results.DeleteResult实例对象
print(*users.find(filter), sep='\n')

删除所有文档

  • users.delete_many({})
    • 删除collection中的所有数据
    • 慎用

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值