返回介绍

第20单元 改善文档存储:MongoDB

发布于 2024-01-28 22:01:16 字数 4444 浏览 0 评论 0 收藏 0

文档存储(即一个NoSQL数据库)是一个具有属性的对象(通常称为文档)的非易失性集合。目前,人们已经开发了许多不同的文档存储的实现方案。本单元重点分析其中一种实现方案——MongoDB,并简要介绍其最主要的竞争对手CouchDB2

2ouchdb.apache.org

MongoDB是一个非关系型数据库。一个MongoDB服务器可以支持多个不相关的数据库。数据库由一个或多个文档集合组成,集合中的所有文档都有唯一的标识符。

在Python中,我们用pymongo模块中MongoClient类的实例来实现MongoDB客户端。可以创建一个无参数的客户端(适用于典型的安装了本地服务器的情况),也可以用服务器的主机名和端口号作为参数创建客户端,或使用服务器的统一资源标识符(URI)作为参数创建客户端:

import pymongo as mongo
# 使用默认的初始化方式
client1 = mongo.MongoClient()
# 指定主机和端口号
client2 = mongo.MongoClient("localhost", 27017)
# 用URI方式指定主机和端口号
client3 = mongo.MongoClient("mongodb://localhost:27017/")

客户一旦端建立了与数据库服务器的连接,就可以选择当前激活的数据库,进而选择激活的集合。您可以使用面向对象(“点”)或字典样式的符号。如果所选的数据库或集合不存在,服务器会立即创建它们:

# 创建并选择活动数据库的两种方法
db = client1.dsdb
db = client1["dsdb"]

# 创建并选择活动集合的两种方法
people = db.people
people = db["people"]

pymongo模块用字典变量来表示MongoDB文档。表示对象的每个字典必须具有_id这个键。如果该键不存在,服务器会自动生成它。

集合对象提供用于在文档集合中插入、搜索、删除、更新、替换和聚合文档以及创建索引的功能。

函数insert_one(doc)和insert_many(docs)将文档或文档列表插入集合。它们分别返回对象InsertOneResult或InsertManyResult,这两个对象分别提供inserted_id和inserted_ids属性。当文档没有明确的键时,就需要使用这些属性来找出文档的键。如果指定了_id键,则在执行插入操作后,该键值也不会改变:

   person1 = {"empname" : "John Smith", "dob" : "1957-12-24"}
   person2 = {"_id" : "XVT162", "empname" : "Jane Doe", "dob" : "1964-05-16"}
   person_id1 = people.insert_one(person1).inserted_id

➾ ObjectId('5691a8720f759d05092d311b')

   # 注意出现了一个新的名为“_id”的键!
   person1

➾ {'empname': 'John Smith', 'dob': '1957-12-24','_id': ObjectId('5691a8720f759d05092d311b')}

   person_id2 = people.insert_one(person2).inserted_id

➾ "XVT162"

   persons = [{"empname" : "Abe Lincoln", "dob" : "1809-02-12"},
              {"empname" : "Anon I. Muss"}]
   result = people.insert_many(persons)
   result.inserted_ids

➾ [ObjectId('5691a9900f759d05092d311c'),ObjectId('5691a9900f759d05092d311d')]

函数find_one()和find()给出匹配可选属性的一个或多个文档,其中find_one()返回文档,而find()返回一个游标(一个生成器),可以使用list()函数将该游标转换为列表,或者在for循环中将其用作迭代器。如果将字典作为参数传递给这些函数中的任意一个,函数将给出与字典的所有键值相等的文档:

   everyone = people.find()
   list(everyone)

➾ [{'empname': 'John Smith', 'dob': '1957-12-24','_id': ObjectId('5691a8720f759d05092d311b')},{'empname': 'Jane Doe', 'dob': '1964-05-16', '_id': 'XVT162'},{'empname': 'Abe Lincoln', 'dob': '1809-02-12','_id': ObjectId('5691a9900f759d05092d311c')},{'empname': 'Anon I. Muss', '_id': ObjectId('5691a9900f759d05092d311d')}]

   list(people.find({"dob" : "1957-12-24"}))

➾ [{'empname': 'John Smith', 'dob': '1957-12-24','_id': ObjectId('5691a8720f759d05092d311b')}]

   people.find_one()

➾ [{'empname': 'John Smith', 'dob': '1957-12-24','_id': ObjectId('5691a8720f759d05092d311b')}]

   people.find_one({"empname" : "Abe Lincoln"})

➾ {'empname': 'Abe Lincoln', 'dob': '1809-02-12','_id': ObjectId('5691a9900f759d05092d311c')}

   people.find_one({"_id" : "XVT162"})

➾ {'empname': 'Jane Doe', 'dob': '1964-05-16', '_id': 'XVT162'}

下面介绍几个实现数据聚合和排序的分组和排序函数。函数sort()对查询的结果进行排序。当以无参数的方式调用它时,该函数按键_id的升序进行排序。函数count()返回查询结果中或整个集合中的文档数量:

   people.count()

➾ 4

   people.find({"dob": "1957-12-24"}).count()

➾ 1

   people.find().sort("dob")

➾ [{'empname': 'Anon I. Muss', '_id': ObjectId('5691a9900f759d05092d311d')},{'empname': 'Abe Lincoln', 'dob': '1809-02-12','_id': ObjectId('5691a9900f759d05092d311c')},{'empname': 'John Smith', 'dob': '1957-12-24','_id': ObjectId('5691a8720f759d05092d311b')},{'empname': 'Jane Doe', 'dob': '1964-05-16', '_id': 'XVT162'}]

函数delete_one(doc)和delete_many(docs)从集合中删除字典doc所标识的一个或多个文档。如果要在删除所有文档的同时保留集合,需使用空字典作为参数调用函数delete_many({}):

   result = people.delete_many({"dob" : "1957-12-24"})
   result.deleted_count

➾ 1

CouchDB

CouchDB是另外一个流行的NoSQL数据库。与MongoDB不同,CouchDB更侧重于可用性而非一致性。对于复制的CouchDB数据库(在多台计算机上运行),所有用户都可以使用它,但却不能保证不同的用户得到的文档是相同的。而对于复制的MongoDB,用户得到的一定是完全相同的文档,但是某些用户可能会无法使用数据库。如果实际使用中不复制数据库,那究竟是采用CouchDB还是MongoDB,就完全取决于个人喜好了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文