Mongodb的学习与实践(1)

之前做项目时候使用的关系性数据库在面对一些不可控的字段情况下,变得很复杂.因此尝试学习下Mongodb,来寻找更快速方便的解决方案.

Mongodb官方有免费的集群云服务器,帮你现搭了由3个mongodb服务组成的集群.如果不想自己本地配置的话,直接去官方注册一下,申请云mongo,然后会给你连接字符串,包括shell,mongodb compass,或者不同语言建立连接的字符串.这样就可以去构建客户端连接.

我这里去注册过了,不过我这里使用的本地的mongodb服务.

我在linux环境下安装,直接去官网下载压缩包,解压,编写配置文件(port,host,path等),然后设置环境变量,最后启动mongo服务.这里细节就不多说了,网上都有安装教程.

实在不会的戳这里https://www.cnblogs.com/xiaofeideboke/p/9837648.html

以下代码均在jupyter-notebook编写

1
2
3
4
5
6
7
8
9
10

import pymongo


client = pymongo.MongoClient("mongodb://127.0.0.1:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false")
db = client.hellofriends # 选择数据库,没有就自动创建一个




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 向数据库中的collection中插入一条数据,hellofriends为collection,如果没有则创建collection
db.hellofriends.insert_one(
{"item": "canvas",
"qty": 100,
"tags": ["cotton"],
"size": {"h": 28, "w": 35.5, "uom": "cm"}}
)

# 向数据库中插入多条数据
result1 = db.hellofriends.insert_many([
{
"name":"syz",
"age":20,
"hobby":"sleep"
},
{
"name":"zjw66",
"age":21,
"hobby":"run"
}
])



1
2
3
4
5
6
7
8

# 通过过滤参数查询指定的数据
# 等价于SELECT * FROM hellofriends WHERE name = "syz"
result = db.hellofriends.find({"name":"syz"})
# result 为游标
for i in result:
print(i)

1
2
3
4
5
6
7


# 等价于SELECT * FROM hellofriends WHERE age in (19, 21)
result = db.hellofriends.find({"age":{"$in":[19,21]}})
for i in result:
print(i)

1
2
3
4
5
6
7


# 等价于 select * from hellofriends where name = "syz" and age < 20
result = db.hellofriends.find({"name":"syz", "age":{"$lt":20}})
for i in result:
print(i)

1
2
3
4
5
6
7
8


# 等价于 select * from hellofriends where name = "syz" or age < 20

result = db.hellofriends.find({"$or":[{"name":"syz"},{"age":{'$lt':21}}]})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11
12
13

# 等价于 select * from hellofriends where name = "syz" and (age < 20 or hobby like 's%')

result = db.hellofriends.find({
"name":"syz",
"$or":[
{"age":{"$lt":20}},
{"hobby":{"$regex":"^s"}}
]
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

from collections import OrderedDict

# 为了确保嵌套的字典是有序的,需要使用OrderedDict或者第三方包bson(垃圾包不要安)
db.hellofriends.insert_many([
{"item": "journal",
"qty": 25,
"size": OrderedDict([("h", 14), ("w", 21), ("uom", "cm")]),
"status": "A"},
{"item": "notebook",
"qty": 50,
"size": OrderedDict([("h", 8.5), ("w", 11), ("uom", "in")]),
"status": "A"},
{"item": "paper",
"qty": 100,
"size": OrderedDict([("h", 8.5), ("w", 11), ("uom", "in")]),
"status": "D"},
{"item": "planner",
"qty": 75,
"size": OrderedDict([("h", 22.85), ("w", 30), ("uom", "cm")]),
"status": "D"},
{"item": "postcard",
"qty": 45,
"size": OrderedDict([("h", 10), ("w", 15.25), ("uom", "cm")]),
"status": "A"}])


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 注意:整个嵌套的文档中的匹配要求需要与指定的文档(包括字段的顺序)要完全一致,
# 字段顺序和之前插入的顺序不对,查不到任何文档

result = db.hellofriends.find({
"size":OrderedDict([("h", 14), ("w", 21), ("uom", "cm")])
})
result1 = db.hellofriends.find({
"size":OrderedDict([ ("w", 21), ("h", 14), ("uom", "cm")])
})
for i in result: # 会显示数据
print(i)
for i in result1: # 不会显示任何数据
print(i)




1
2
3
4
5
6
7
8
9

# 通过.符号来获取嵌套的文档

result = db.hellofriends.find({
"size.h":{"$lt":15}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 插入数组

db.hellofriends.insert_many([
{"item": "journal",
"qty": 25,
"tags": ["blank", "red"],
"dim_cm": [14, 21]},
{"item": "notebook",
"qty": 50,
"tags": ["red", "blank"],
"dim_cm": [14, 21]},
{"item": "paper",
"qty": 100,
"tags": ["red", "blank", "plain"],
"dim_cm": [14, 21]},
{"item": "planner",
"qty": 75,
"tags": ["blank", "red"],
"dim_cm": [22.85, 30]},
{"item": "postcard",
"qty": 45,
"tags": ["blue"],
"dim_cm": [10, 15.25]}])

1
2
3
4
5
6
7
8

# 搜索指定tags顺序的文档,要考虑顺序,并且是精准查询,只含有red和blank
result = db.hellofriends.find({
"tags":["red","blank"]
})
for i in result:
print(i)

1
2
3
4
5
6
7
8

# 搜索包含red和blank数组,但不考虑他们的顺序
result = db.hellofriends.find({
"tags":{"$all":["red","blank"]}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9

# 查找数组中存在某个元素的文档

result = db.hellofriends.find({
"tags":"red"
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9

# 对查找数组中的元素增加条件,只要数组中有满足某一个元素大于25且另外一个元素大于23

result = db.hellofriends.find({
"dim_cm":{"$gt":25,"$lt":23}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11

# 数组中需满足存在一个元素既大于23,又小于25就可以了
# $elemMatch表示 至少存在一个满足所有的条件的文档

result = db.hellofriends.find({
"dim_cm":{"$elemMatch":{"$gt":22, "$lt":25}}
})
for i in result:
print(i)


1
2
3
4
5
6
7
8
9
10

# 查找满足某些条件下数组中某个具体索引位置的元素
# 例如查找dim_cm数组中索引为1的并>22的元素

result = db.hellofriends.find({
"dim_cm.0":{"$gt":21}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10

# 通过数组的长度查找对应的文档

result = db.hellofriends.find({
"tags":{"$size":3}
})
for i in result:
print(i)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 数组中嵌套
from collections import OrderedDict
db.hellofriends.insert_many([
{"item": "journal",
"instock": [
OrderedDict([("warehouse", "A"), ("qty", 5)]),
OrderedDict([("warehouse", "C"), ("qty", 15)])]},
{"item": "notebook",
"instock": [
OrderedDict([("warehouse", "C"), ("qty", 5)])]},
{"item": "paper",
"instock": [
OrderedDict([("warehouse", "A"), ("qty", 60)]),
OrderedDict([("warehouse", "B"), ("qty", 15)])]},
{"item": "planner",
"instock": [
OrderedDict([("warehouse", "A"), ("qty", 40)]),
OrderedDict([("warehouse", "B"), ("qty", 5)])]},
{"item": "postcard",
"instock": [
OrderedDict([("warehouse", "B"), ("qty", 15)]),
OrderedDict([("warehouse", "C"), ("qty", 35)])]}])

1
2
3
4
5
6
7
8
9
10

from collections import OrderedDict

# 精确查询某个嵌套的文档(精确查询要按照字典顺序)
result = db.hellofriends.find({
"instock":OrderedDict([("warehouse", "A"), ("qty", 5)])
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10

# 查找只要数组中存在满足的条件即可

# 查找instock中的 qty>=50 的文档
result = db.hellofriends.find({
"instock.qty":{"$gte":50}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10

# 查找数组中指定索引的并满足条件的文档

# 查找instock数组中索引为0且 qty<=10 的文档
result = db.hellofriends.find({
"instock.0.qty":{"$lte":10}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11


# elemMatch操作符
# 寻找满足instock数组中,6<=qty<=20条件下至少存在一条子文档的文档

result = db.hellofriends.find({
"instock":{"$elemMatch":{"qty":{"$lte":20,"$gte":6}}}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10

# 查找满足instock数组中,qty >= 6 or qty <= 20 条件下至少存在一条子文档的文档
result = db.hellofriends.find({
"instock.qty":{"$lte":20,"$gte":6}
})
for i in result:
print(i)



1
2
3
4
5
6
7
8

# 查找满足qty=5且warehouse=”A“的至少一条文档
result = db.hellofriends.find({
"instock.qty":5,"instock.warehouse":"A"
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 用于限定查询文档字段量的demo
db.hellofriends.insert_many([
{"item": "journal",
"status": "A",
"size": {"h": 14, "w": 21, "uom": "cm"},
"instock": [{"warehouse": "A", "qty": 5}]},
{"item": "notebook",
"status": "A",
"size": {"h": 8.5, "w": 11, "uom": "in"},
"instock": [{"warehouse": "C", "qty": 5}]},
{"item": "paper",
"status": "D",
"size": {"h": 8.5, "w": 11, "uom": "in"},
"instock": [{"warehouse": "A", "qty": 60}]},
{"item": "planner",
"status": "D",
"size": {"h": 22.85, "w": 30, "uom": "cm"},
"instock": [{"warehouse": "A", "qty": 40}]},
{"item": "postcard",
"status": "A",
"size": {"h": 10, "w": 15.25, "uom": "cm"},
"instock": [
{"warehouse": "B", "qty": 15},
{"warehouse": "C", "qty": 35}]}])


1
2
3
4
5
6
7
8

# 默认返回包含所有字段的文档
result = db.hellofriends.find({
"status":"A"
})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 返回指定fields的文档

# 返回的文档中只包含item和status和_id字段,
# 默认包含_id字段(即无需显示指定_id字段),可以通过显示显示"_id":0,来排出该字段

# 等价于select _id, item, status fro hellofriends where status = "A"


result = db.hellofriends.find(
{"status":"A"}, {"item":1, "status":1} # 添加限制约束条件
)
for i in result:
print(i)

1
2
3
4
5
6
7
8


result = db.hellofriends.find({
"status":"A"
},{"status":0, "instock":0, "item":0})
for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10
11

# 对嵌套的文档执行指定字段的映射

# 可以使用.fields,无法使用.index
result = db.hellofriends.find({
"status":"A"
},{"item":1, "status":1, "size.uom":1, "instock.qty":1})

for i in result:
print(i)

1
2
3
4
5
6
7
8
9
10

# $slice表示查询结果的数组中指定的元素数量

# 选择显示一个元素
result = db.hellofriends.find({
"status":"A"
},{"item":1, "instock":{"$slice":1}})
for i in result:
print(i)

1
2
3
4
5
6

# 查询null数据或者缺失的字段

db.hellofriends.insert_many([{"_id": 1, "item": None}, {"_id": 2}])


1
2
3
4
5
6
7
8
9

# 精确查询,查找item为null或者不包含item字段的文档
result = db.hellofriends.find({
"item":None
})
for i in result:
print(i)


1
2
3
4
5
6
7
8

# 文档类型检查,10表示为null,只查询item为null的文档
result = db.hellofriends.find({
"item":{"$type":10}
})
for i in result:
print(i)

1
2
3
4
5
6
7
8

# 只查询item不存在(并不是null or ‘’)的文档,区别于关系sql,关系sql只有null or ''
result = db.hellofriends.find({
"item":{"$exists":False}
})
for i in result:
print(i)