python连接MongoDB数据库
2025-01-13 08:54 阅读(104)

本篇文章讲了用python连接MongoDB数据库,并用python代码对MongoDB数据库进行增删改查等操作。

数据库连接

代码中的 MongoDB 类以 __init__ 方法作为起点,通过 pymongo.MongoClient 建立起与本地运行在 127.0.0.1 地址、端口 27017 的 MongoDB 服务器的连接。这一连接操作看似平常,实则是整个数据处理流程的根基,它精准定位到名为 demo4 的数据库中的 info 集合,为后续所有操作搭建起稳定的 “桥梁”,确保数据的读写、分析等活动能够有序开展。

def __init__(self):
    self.client = pymongo.MongoClient(host='127.0.0.1', port=27017)
    self.db = self.client['demo4']['info']

基础数据操作

(一)数据插入


插入单条文档:insert_one_document 方法提供了一种向指定集合插入单条数据的便捷方式。在实际应用场景中,比如构建一个学术研究项目的样本数据库,每一条记录都可能对应着一个研究对象的详细信息。该方法接收以字典形式表示的文档数据,像是 {"participant_id": "001", "age": 25, "field_of_study": "Computer Science"},然后利用 insert_one 函数将其插入到相应集合中,并返回该文档在数据库中自动生成的独一无二的 _id。这个 _id 不仅是数据的标识,更是后续进行精准查询、更新或删除操作的关键依据。

def insert_one_document(self, collection_name, document):
    """
    collection_name: 集合名称
    document: 要插入的文档数据,以字典形式表示
    return: 返回插入文档的_id
    """
    collection = self.db[collection_name]
    result = collection.insert_one(document)
    return result.inserted_id

插入多条文档:当面临大量数据需要一次性录入时,insert_many_documents 方法就发挥了重要作用。例如在收集大规模调查问卷数据时,可能会有众多受访者的信息需要批量存储。它接收一个包含多个文档字典的列表,借助 insert_many 函数高效地将多条数据同时插入集合,返回的插入结果对象方便我们进一步了解插入操作的详细情况,如获取所有插入文档的 _id 列表,确保数据批量导入的完整性和准确性。

def insert_many_documents(self, collection_name, documents):
    """
    collection_name: 集合名称
    documents: 要插入的文档数据列表,每个元素为字典形式
    :return: 返回插入结果对象
    """
    collection = self.db[collection_name]
    result = collection.insert_many(documents)
    return result

(二)数据查询


查找单条文档:在复杂的数据集合中,我们常常需要快速定位某一条特定的信息。find_one_document 方法就像一把精准的 “钥匙”,通过接收集合名称以及明确的查询条件字典(例如 {"participant_id": "001"}),能够在海量数据中迅速找到符合条件的那条文档。若没有匹配的文档,它也会返回 None,为我们的查询操作提供明确的反馈,避免出现数据查找的 “盲区”。

def find_documents(self, collection_name, query=None):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示,默认为None表示查找所有文档
    return: 返回游标对象,可用于遍历查找到的文档
    """
    collection = self.db[collection_name]
    if query is None:
        query = {}
    return collection.find(query)

查找多条文档:有时候,我们需要获取满足特定条件的一组数据,而非仅仅一条。find_documents 方法则可以胜任这一任务,当不指定查询条件(默认为 None,即查找所有文档)时,它会将整个集合中的数据一网打尽;而当传入精心构造的查询条件,如 {"age": {"$gt": 20}}(表示查找年龄大于 20 岁的所有文档),它会以游标对象的形式返回所有符合条件的文档,方便我们后续逐一遍历查看,进行进一步的分析或处理。

def find_one_document(self, collection_name, query):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示
    return: 返回符合条件的一条文档(字典形式),如果没找到则返回None
    """
    collection = self.db[collection_name]
    return collection.find_one(query)

(三)数据更新


更新单条文档:数据并非一成不变,随着研究的深入或项目的推进,我们可能需要对已存储的数据进行修改。update_one_document 方法就像是一位精细的 “工匠”,它依据给定的集合名称、用于准确锁定目标文档的查询条件(比如 {"participant_id": "001"})以及包含更新内容的字典(像 {"$set": {"field_of_study": "Data Science"}},巧妙运用 MongoDB 的更新操作符),对单个文档进行精准更新,并返回更新结果对象,让我们能够清晰知晓此次更新操作是否成功实施,确保数据的时效性和准确性。

def update_one_document(self, collection_name, query, update):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示,用于定位要更新的文档
    update: 更新内容,以字典形式表示,如{"$set": {"field": "new_value"}}
    :return: 返回更新结果对象
    """
    collection = self.db[collection_name]
    result = collection.update_one(query, update)
    return result

更新多条文档:当需要对一批符合特定条件的文档统一进行修改时,update_many_documents 方法就派上用场了。例如,若要将所有年龄小于 30 岁的参与者的研究领域统一更新为某一特定值,只需指定相应的集合名称、查询条件(如 {"age": {"$lt": 30}})以及更新内容,它就能一次性对所有匹配的文档完成更新操作,大大提高了数据更新的效率,同时保证了数据的一致性。

def update_many_documents(self, collection_name, query, update):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示,用于定位要更新的文档
    update: 更新内容,以字典形式表示,如{"$set": {"field": "new_value"}}
    return: 返回更新结果对象
    """
    collection = self.db[collection_name]
    result = collection.update_many(query, update)
    return result

(四)数据删除


删除单条文档:对于那些因各种原因不再需要的单条数据,delete_one_document 方法提供了有效的清理手段。只需提供集合名称和能够准确识别目标文档的查询条件(例如 {"participant_id": "002"}),它就能将对应的文档从集合中删除,并通过返回的删除结果对象告知我们操作是否成功执行,确保数据存储的精简性和有效性。

def delete_one_document(self, collection_name, query):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示,用于定位要删除的文档
    return: 返回删除结果对象
    """
    collection = self.db[collection_name]
    result = collection.delete_one(query)
    return result

删除多条文档:在某些情况下,可能需要批量删除一批符合特定条件的数据,比如清除某个特定时间段之前的所有记录。delete_many_documents 方法能够轻松应对这种需求,通过指定集合名称和相应的查询条件(如 {"collection_date": {"$lt": "2023-01-01"}}),它会将所有满足条件的文档一次性删除,为数据库腾出宝贵的空间,同时维持数据的合理规模和结构。


python 代码解读复制代码

def delete_many_documents(self, collection_name, query):
    """
    collection_name: 集合名称
    query: 查询条件,以字典形式表示,用于定位要删除的文档
    return: 返回删除结果对象
    """
    collection = self.db[collection_name]
    result = collection.delete_many(query)
    return result

聚合分析

(一)分组统计与汇总


按年龄分组求和:group_and_sum_by_age 方法开启了我们对数据进行分组聚合分析的大门。通过构建一个包含 $group 操作符的聚合管道,以 $age 作为分组依据,利用 $sum 操作符对每个年龄组内的 $age 字段值进行求和,并将结果存储在 sum_age 字段中。这种操作在分析不同年龄层次的数据特征时非常实用,比如在医学研究中统计不同年龄段患者的某项指标总和,为进一步探索年龄与该指标之间的关系提供有力的数据支持。

def group_and_sum_by_age(self):
    """
    :return: 返回聚合操作结果(游标对象),可用于遍历每个年龄组的统计结果
    """
    pipeline = [
        {'$group': {"_id": "$age", "sum_age": {"$sum": "$age"}}}
    ]
    return self.db.aggregate(pipeline)

按年龄分组计数:group_and_count_by_age 方法则专注于统计每个年龄组中的文档数量,也就是各个年龄段的人数分布情况。同样借助 $group 操作符,以 $age 为分组标识,通过 $sum 操作符传入 1 来实现计数功能,将结果存放在 count 字段中。这有助于我们快速了解数据在年龄维度上的分布密度,在社会学、人口学等领域的研究中能够帮助我们把握不同年龄段人群的占比情况。

def group_and_count_by_age(self):
    """
    :return: 返回聚合操作结果(游标对象),可用于遍历每个年龄组的统计结果
    """
    pipeline = [
        {'$group': {"_id": "$age", "count": {"$sum": 1}}}
    ]
    return self.db.aggregate(pipeline)

综合年龄统计:group_and_calculate_age_stats 方法更进一步,在一次聚合操作中同时计算每个年龄组的年龄总和、平均年龄以及人数。通过巧妙组合多个聚合操作符,它为我们呈现出了更为全面的年龄相关数据画像,使我们能够从多个角度深入分析年龄因素在数据中的影响,无论是在市场调研中分析不同年龄消费者的消费能力,还是在教育领域研究不同年龄段学生的学习成绩分布,都能提供极具价值的洞察。

def group_and_calculate_age_stats(self):
    """
    :return: 返回聚合操作结果(游标对象),可用于遍历每个年龄组的统计结果
    """
    pipeline = [
        {'$group': {"_id": "$age", "count": {"$sum": 1}, "avg_age": {"$avg": "$age"}, "sum_age": {"$sum": "$age"}}}
    ]
    return self.db.aggregate(pipeline)

(二)筛选与分组结合的深度洞察


按年龄筛选并按性别分组统计:在实际数据分析中,我们常常需要先根据某个条件筛选数据,再进行分组统计。match_by_age_greater_than 方法可以帮助我们筛选出年龄大于特定值的文档,在此基础上,match_and_group_by_gender_after_age_filter 方法进一步按照性别对筛选后的文档进行分组,并统计每组的人数。这种先筛选后分组的操作方式,能够让我们聚焦于特定年龄区间内不同性别的数据特征,例如在健康研究中分析特定年龄段男性和女性的健康指标差异,为针对性的研究和决策提供精准的数据依据。

def match_by_age_greater_than(self, age_value):
    """
    age_value: 用于比较的年龄值
    :return: 返回聚合操作结果(游标对象),可用于遍历筛选后的文档
    """
    pipeline = [
        {"$match": {"age": {"$gt": age_value}}}
    ]
    return self.db.aggregate(pipeline)
def match_and_group_by_gender_after_age_filter(self, age_value):
    """
    age_value: 用于筛选年龄的阈值
    :return: 返回聚合操作结果(游标对象),可用于遍历分组统计后的结果
    """
    pipeline = [
        {"$match": {"age": {"$gt": age_value}}},
        {'$group': {"_id": "$gender", "count": {"$sum": 1}}}
    ]
    return self.db.aggregate(pipeline)

带姓名收集的筛选与分组:match_and_group_by_gender_with_name_collection_after_age_filter 方法则在上述基础上进行了拓展,不仅统计每组人数,还通过 $push 操作符将每个性别组内对应的姓名收集到一个数组中。这使得我们在分析数据时,除了了解数量关系外,还能具体知晓涉及哪些个体,在团队协作研究、项目参与人员分析等场景中,能够更全面地掌握不同性别群体的构成情况,丰富了数据分析的维度和深度。

def match_and_group_by_gender_with_name_collection_after_age_filter(self, age_value):
    """
    age_value: 用于筛选年龄的阈值
    :return: 返回聚合操作结果(游标对象),可用于遍历分组统计后的结果
    """
    pipeline = [
        {"$match": {"age": {"$gt": age_value}}},
        {'$group': {
            "_id": "$gender",
            "count": {"$sum": 1},
            "names": {"$push": "$name"}}}
    ]
    return self.db.aggregate(pipeline)

(三)结果控制与排序展示


控制输出字段:project_specific_fields 方法赋予了我们对聚合结果输出结构的控制权。根据我们指定的字段列表(例如 ["name", "age", "field_of_study"]),它运用 $project 操作符对结果进行精心 “裁剪”,隐藏那些我们不关注的字段,包括默认的 _id 字段,只展示核心信息,使得最终呈现的数据更加简洁明了,便于我们聚焦关键内容进行分析和解读,避免了数据冗余带来的干扰。

def project_specific_fields(self, fields):
    """
    fields: 要显示的字段列表,例如 ["name", "age"]
    :return: 返回聚合操作结果(游标对象),可用于遍历输出结构调整后的文档
    """
    projection = {field: 1 for field in fields}
    projection["_id"] = 0
    pipeline = [
        {"$project": projection}
    ]
    return self.db.aggregate(pipeline)

排序结果展示:sort_by_age 方法则为我们提供了按照年龄对文档进行排序的功能,通过设置 ascending 参数,我们可以轻松选择升序(默认)或降序排列方式。在分析数据趋势、比较不同年龄阶段的数据特征时,有序的数据展示能够帮助我们更直观地发现规律,例如在长期跟踪研究中观察某个变量随年龄增长的变化趋势,排序后的结果能够让这种趋势一目了然

def sort_by_age(self, ascending=True):
    """
    ascending: 是否升序排序,默认为True,若为False则降序排序
    :return: 返回聚合操作结果(游标对象),可用于遍历排序后的文档
    """
    order = 1 if ascending else -1
    pipeline = [
        {"$sort": {"age": order}}
    ]
    return self.db.aggregate(pipeline)

(四)限制与跳过


限制返回数量:在面对海量数据时,我们有时并不需要查看全部结果,而是希望快速获取部分代表性的数据进行初步分析。limit_results 方法就像是一个数据的 “调节阀”,通过设置 limit_value,我们可以限制聚合管道返回的文档数量,比如只查看前 10 条数据,从而快速把握数据的大致情况,提高数据分析的效率,尤其在大数据探索阶段,能够帮助我们迅速定位到有价值的数据线索。

def limit_results(self, limit_value):
    """
    limit_value: 要返回的文档数量限制值
    :return: 返回聚合操作结果(游标对象),可用于遍历限制数量后的文档
    """
    pipeline = [
        {"$limit": limit_value}
    ]
    return self.db.aggregate(pipeline)

跳过部分数据:与之配合的 skip_results 方法则提供了跳过指定数量文档的功能,例如在实现分页浏览效果时,我们可以通过跳过前面若干页的数据,直接查看后面页面的数据内容。这两个方法相互协作,让我们能够更加灵活地驾驭数据展示的节奏和范围,根据实际需求精准获取所需的数据子集。

def skip_results(self, skip_value):
    """
    skip_value: 要跳过的文档数量
    :return: 返回聚合操作结果(游标对象),可用于遍历跳过指定数量后的文档
    """
    pipeline = [
        {"$skip": skip_value}
    ]
    return self.db.aggregate(pipeline)

好了大致就是这些了,当然这些函数只是个例子,真正要应用要根据自己的需求修改,这一部分算MongoDB的精髓,我也是刚学,有什么不对的地方请各位大佬指教!!


作者:katkal

链接:https://juejin.cn