Python 操作 MongoDB:增、删、改、查

MongoDB 教程、高级教程:https://www.runoob.com/mongodb/mongodb-tutorial.html

官网:https://www.mongodb.com/

Pymongo 多线程安全。多进程不保证安全

Pymongo "多线程" 是安全的。"多进程"不保证是安全的。如果想要 多进程 同时写入同一个 collection中,需要在每个进程中创建自己的MongoClient对象。

官方文档:https://pymongo.readthedocs.io/en/stable/faq.html?highlight=thread#is-pymongo-thread-safe

pymongo.MongoClient 类初始化

https://www.mongodb.com/docs/manual/reference/connection-string/

参数说明

host 参数可以是 完整的 mongodb URI <http://dochub.mongodb.org/core/connections>
密码中如果包含保留字符: ':', '/', '+' and '@' 必须按照RFC2396编码:
    from urllib.parse import quote_plus

    uri = "mongodb://%s:%s@%s" % (
        quote_plus(user), quote_plus(password), host)
    client = MongoClient(uri)

参数:( 更详细说明,看源码中注释 )
  - `host` (可选,默认:127.0.0.1): hostname、IP地址、mongodb URI    
  - `port` (可选,默认:27017): 端口号。
  - `document_class` (optional): 用于此客户机上查询返回的文档的默认类
  - `tz_aware` (optional): if ``True``,
    :class:`~datetime.datetime` instances returned as values
    in a document by this :class:`MongoClient` will be timezone
    aware (otherwise they will be naive)

  - `type_registry` (optional): instance of
    :class:`~bson.codec_options.TypeRegistry` to enable encoding
    and decoding of custom types.
  - `datetime_conversion`:   
        指定如何在BSON中解码UTC日期时间。有效的选项包括
        'datetime_ms'作为日期时间返回,
        'datetime'作为日期时间返回。默认为'datetime'。
        'datetime_auto'用于在基础日期时间超出范围时返回DatetimeMS对象,
        'datetime_clamp'用于钳住最小和最大可能的日期时间。
        See :ref:`handling-out-of-range-datetimes` for details.

**其他可选参数通过 **kwargs 传递
  - `directConnection` (optional): 
  - `maxPoolSize` (optional): 
  - `minPoolSize` (optional): 
  - `maxIdleTimeMS` (optional): 
  - `maxConnecting` (optional): 
  - `timeoutMS`: 
  - `socketTimeoutMS`: 
  - `connectTimeoutMS`: 
  - `server_selector`: 
  - `serverSelectionTimeoutMS`: 
  - `waitQueueTimeoutMS`: 
  - `heartbeatFrequencyMS`:
  - `appname`: 
  - `driver`: 
  - `event_listeners`:
  - `retryWrites`: 
  - `retryReads`: 
  - `compressors`: 
  - `zlibCompressionLevel`:
  - `uuidRepresentation`: 
  - `unicode_decode_error_handler`: 
  - `srvServiceName`: 
  - `w`: 
  - `wTimeoutMS`: 
  - `journal`: 
  - `fsync`: 
  - `replicaSet`: 
  - `readPreference`: 
  - `readPreferenceTags`: 
  - `maxStalenessSeconds`: 
  - `username`: A string.
  - `password`: A string.
  - `authSource`: 在哪个database上进行认证. 默认在URI中指定,

                           URI中没有指定时默认是admin.
  - `authMechanism`: 
  - `authMechanismProperties`: 
  - `tls`: 
  - `tlsInsecure`: 
  - `tlsAllowInvalidCertificates`:
  - `tlsAllowInvalidHostnames`:
  - `tlsCAFile`: 
  - `tlsCertificateKeyFile`: 
  - `tlsCRLFile`: 
  - `tlsCertificateKeyFilePassword`: 
  - `tlsDisableOCSPEndpointCheck`: 
  - `ssl`: 
  - `readConcernLevel`:
  - `auto_encryption_opts`: 
  - `server_api`: 

PyMongo 连接有用户名和密码的数据库

注意:该方法在 PyMongo 4.x 中被删除!!!

import pymongo

client = pymongo.MongoClient(host='host', port=27017)
# info_data 需要用户名和密码进行身份认证的数据库
db = client.info_data
# username:用户名;password:密码
db.authenticate('username', 'password')
print(db.list_collection_names())

方法 1:通过 ip、port

import pymongo

client = pymongo.MongoClient(
    # 主机
    host=host,
    # 端口
    port=port,
    # 用户名
    username=username,
    # 密码
    password=password,
    # 需要用户名和密码进行身份认证的数据库
    authSource='info_data'
)
db = client.info_data
print(db.list_collection_names())

方法 2:通过 mongo uri

import pymongo

client = pymongo.MongoClient('mongodb://username:password@host:port/?authSource=info_data')
db = client.info_data
print(db.list_collection_names())

示例 1:简单封装

# -*- coding: utf-8 -*-

import json
import pymongo


class MongoDBOperate(object):

    def __init__(self, host=None, port=27017, username=None, password=None):
        super(MongoDBOperate, self).__init__()
        mongodb_config = dict(
            host=host,
            port=port,
            username=username,
            password=password,
        )
        self.__client = pymongo.MongoClient(**mongodb_config)
        pass

    def __del__(self):
        """
            析构函数,释放资源或者关闭连接
        :return:
        """
        # self.__client.close()
        pass

    def insert_one_or_many(self, db_name=None, tb_name=None, data=None):
        """
            插入一条
        :param db_name:   数据库名
        :param tb_name:   集合名(表名)
        :param data:      插入的数据(文档): dict 类型 或者 list 类型
        """
        if db_name and tb_name and data:
            mongodb_tb = self.__client.get_database(db_name).get_collection(tb_name)
            if isinstance(data, list):
                mongodb_tb.insert_many(data)
            else:
                _id = data.get('_id', None)
                if _id:
                    filter_condition = {'_id': _id}
                    # 替换文档(upsert=True, 存在则覆盖,不存在则插入)
                    mongodb_tb.replace_one(filter_condition, data, upsert=True)
                else:
                    mongodb_tb.insert_one(data)
        else:
            raise Exception('db_name or tb_name is None')

    def find_one_or_many(self, db_name=None, tb_name=None, query_condition=None, field_list: list = None,
                         query_one=False):
        """
        :param db_name: 数据库名
        :param tb_name: 数据表名
        :param query_condition: 查询条件
        :param field_list: 要查询的字段列表
        :param query_one: 是否只查询一条数据
        :return:
        """
        if db_name and tb_name:
            mongodb_tb = self.__client.get_database(db_name).get_collection(tb_name)
            if query_condition:
                func_find = mongodb_tb.find_one if query_one else mongodb_tb.find
                query_field = {field: 1 for field in field_list} if field_list else None
                result_list = func_find(query_condition, query_field) if field_list else func_find(query_condition)
            else:
                # 没有查询条件,默认返回所有
                query_field = {field: 1 for field in field_list} if field_list else None
                result_list = mongodb_tb.find({}, query_field) if field_list else mongodb_tb.find()
            for result in result_list:
                yield result
        else:
            raise Exception('db_name or tb_name is None')

    def update_one_or_many(self, db_name=None, tb_name=None, update_condition=None, update_one=True, update_id=None, ):
        """
            Update a single document matching the filter ( update_condition )
        :param db_name:
        :param tb_name:
        :param update_condition:  filter 条件
        :param update_one:
        :param update_id: 根据 _id 进行更新
        :return:
        """
        if db_name and tb_name and update_condition:
            mongodb_tb = self.__client.get_database(db_name).get_collection(tb_name)
            if update_id:
                result = mongodb_tb.update_one({'_id': update_id}, update_condition)
                return result
            func_update = mongodb_tb.update_one if update_one else mongodb_tb.update_many
            result = func_update(update_condition)
        else:
            raise Exception('db_name or tb_name or update_condition is None')
        return result

    def remove_one_or_many(self, db_name=None, tb_name=None, remove_condition=None, remove_one=True):
        if db_name and tb_name and remove_condition:
            mongodb_tb = self.__client.get_database(db_name).get_collection(tb_name)
            # remove_condition = { "name": "test_test" }
            func_delete = mongodb_tb.delete_one if remove_one else mongodb_tb.delete_many
            func_delete(filter=remove_condition)
        else:
            raise Exception('db_name or tb_name or remove_condition is None')


if __name__ == '__main__':
    mongo_db = MongoDBOperate(
        host='127.0.0.1',
        username='admin_username',
        password='xxxxxxxx'
    )
    mongo_db.insert_one_or_many('test_db', 'test_test', {'test_data': 'test_data'})
    pass

示例 2:( feapder 项目 MongoDB )

feapder 项目的 db 操作:https://github.com/Boris-code/feapder/tree/master/feapder/db

import re
import pymongo
from pymongo import MongoClient
from pymongo.database import Database
from pymongo.collection import Collection
from typing import List, Dict, Optional
from pymongo.errors import DuplicateKeyError, BulkWriteError
from loguru import logger


class MongoDB(object):

    def __init__(self, host='127.0.0.1', port=27017, db='admin', username=None, password=None, **kwargs):
        if host.startswith('mongodb://'):
            self.client = MongoClient(host=host)
        else:
            mongo_db_config = dict(
                host=host, port=port,
                username=username, password=password
            )
            self.client = MongoClient(host=host)
            kwargs.update(mongo_db_config)
            self.client = MongoClient(**kwargs)
        self.db = self.get_database(db)
        # 缓存索引信息
        self.__index__cached = {}
        pass

    def __del__(self):
        pass

    def get_database(self, database, **kwargs) -> Database:
        """
        获取数据库对象
        @param database: 数据库名
        @return:
        """
        return self.client.get_database(database, **kwargs)

    def get_collection(self, coll_name, **kwargs) -> Collection:
        """
        根据集合名获取集合对象
        @param coll_name: 集合名
        @return:
        """
        return self.db.get_collection(coll_name, **kwargs)

    def find(
            self, coll_name: str, condition: Optional[Dict] = None, limit: int = 0, **kwargs
    ) -> List[Dict]:
        """
        @summary:
        无数据: 返回[]
        有数据: [{'_id': 'xx', ...}, ...]
        ---------
        @param coll_name: 集合名(表名)
        @param condition: 查询条件
        @param limit: 结果数量
        @param kwargs:
            更多参数 https://docs.mongodb.com/manual/reference/command/find/#command-fields

        ---------
        @result:
        """
        condition = {} if condition is None else condition
        command = {"find": coll_name, "filter": condition, "limit": limit}
        command.update(kwargs)
        result = self.run_command(command)
        cursor = result["cursor"]
        cursor_id = cursor["id"]
        dataset = cursor["firstBatch"]
        while True:
            if cursor_id == 0:
                break
            result = self.run_command(
                {
                    "getMore": cursor_id,
                    "collection": coll_name,
                    "batchSize": kwargs.get("batchSize", 100),
                }
            )
            cursor = result["cursor"]
            cursor_id = cursor["id"]
            dataset.extend(cursor["nextBatch"])
        return dataset

    def add(
            self,
            coll_name,
            data: Dict,
            replace=False,
            update_columns=(),
            update_columns_value=(),
            insert_ignore=False,
    ):
        """
        添加单条数据
        Args:
            coll_name: 集合名
            data: 单条数据
            replace: 唯一索引冲突时直接覆盖旧数据,默认为False
            update_columns: 更新指定的列(如果数据唯一索引冲突,则更新指定字段,如 update_columns = ["name", "title"]
            update_columns_value: 指定更新的字段对应的值, 不指定则用数据本身的值更新
            insert_ignore: 索引冲突是否忽略 默认False

        Returns: 插入成功的行数

        """
        affect_count = 1
        collection = self.get_collection(coll_name)
        try:
            collection.insert_one(data)
        except DuplicateKeyError as e:
            # 存在则更新
            if update_columns:
                if not isinstance(update_columns, (tuple, list)):
                    update_columns = [update_columns]

                condition = self.__get_update_condition(
                    coll_name, data, e.details.get("errmsg")
                )

                # 更新指定的列
                if update_columns_value:
                    # 使用指定的值更新
                    doc = {
                        key: value
                        for key, value in zip(update_columns, update_columns_value)
                    }
                else:
                    # 使用数据本身的值更新
                    doc = {key: data[key] for key in update_columns}

                collection.update_one(condition, {"$set": doc})

            # 覆盖更新
            elif replace:
                condition = self.__get_update_condition(
                    coll_name, data, e.details.get("errmsg")
                )
                # 替换已存在的数据
                collection.replace_one(condition, data)

            elif not insert_ignore:
                raise e

        return affect_count

    def add_batch(
            self,
            coll_name: str,
            datas: List[Dict],
            replace=False,
            update_columns=(),
            update_columns_value=(),
            condition_fields: dict = None,
    ):
        """
        批量添加数据
        Args:
            coll_name: 集合名
            datas: 数据 [{'_id': 'xx'}, ... ]
            replace:  唯一索引冲突时直接覆盖旧数据,默认为False
            update_columns: 更新指定的列(如果数据的唯一索引存在,则更新指定字段,如 update_columns = ["name", "title"]
            update_columns_value: 指定更新的字段对应的值, 不指定则用数据本身的值更新
            condition_fields: 用于条件查找的字段,不指定则用索引冲突中的字段查找

        Returns: 添加行数,不包含更新

        """
        add_count = 0

        if not datas:
            return add_count

        collection = self.get_collection(coll_name)
        if not isinstance(update_columns, (tuple, list)):
            update_columns = [update_columns]

        try:
            add_count = len(datas)
            collection.insert_many(datas, ordered=False)
        except BulkWriteError as e:
            write_errors = e.details.get("writeErrors")
            for error in write_errors:
                if error.get("code") == 11000:
                    # 数据重复
                    # 获取重复的数据
                    data = error.get("op")

                    def get_condition():
                        # 获取更新条件
                        if condition_fields:
                            condition = {
                                condition_field: data[condition_field]
                                for condition_field in condition_fields
                            }
                        else:
                            # 根据重复的值获取更新条件
                            condition = self.__get_update_condition(
                                coll_name, data, error.get("errmsg")
                            )

                        return condition

                    if update_columns:
                        # 更新指定的列
                        if update_columns_value:
                            # 使用指定的值更新
                            doc = {
                                key: value
                                for key, value in zip(
                                    update_columns, update_columns_value
                                )
                            }
                        else:
                            # 使用数据本身的值更新
                            doc = {key: data.get(key) for key in update_columns}

                        collection.update_one(get_condition(), {"$set": doc})
                        add_count -= 1

                    elif replace:
                        # 覆盖更新
                        collection.replace_one(get_condition(), data)
                        add_count -= 1

                    else:
                        # log.error(error)
                        add_count -= 1

        return add_count

    def count(self, coll_name, condition: Optional[Dict], limit=0, **kwargs):
        """
        计数
        @param coll_name: 集合名
        @param condition: 查询条件
        @param limit: 限制数量
        @param kwargs:
        ----
        command = {
          count: <collection or view>,
          query: <document>,
          limit: <integer>,
          skip: <integer>,
          hint: <hint>,
          readConcern: <document>,
          collation: <document>,
          comment: <any>
        }
        https://docs.mongodb.com/manual/reference/command/count/#mongodb-dbcommand-dbcmd.count
        @return: 数据数量
        """
        command = {"count": coll_name, "query": condition, "limit": limit, **kwargs}
        result = self.run_command(command)
        return result["n"]

    def update(self, coll_name, data: Dict, condition: Dict, upsert: bool = False):
        """
        更新
        Args:
            coll_name: 集合名
            data: 单条数据 {"xxx":"xxx"}
            condition: 更新条件 {"_id": "xxxx"}
            upsert: 数据不存在则插入,默认为 False

        Returns: True / False
        """
        try:
            collection = self.get_collection(coll_name)
            collection.update_one(condition, {"$set": data}, upsert=upsert)
        except Exception as e:
            logger.error(
                """
                error:{}
                condition: {}
            """.format(
                    e, condition
                )
            )
            return False
        else:
            return True

    def delete(self, coll_name, condition: Dict) -> bool:
        """
        删除
        Args:
            coll_name: 集合名
            condition: 查找条件
        Returns: True / False

        """
        try:
            collection = self.get_collection(coll_name)
            collection.delete_one(condition)
        except Exception as e:
            logger.error(
                """
                error:{}
                condition: {}
            """.format(
                    e, condition
                )
            )
            return False
        else:
            return True

    def run_command(self, command: Dict):
        """
        运行指令
        参考文档 https://www.geek-book.com/src/docs/mongodb/mongodb/docs.mongodb.com/manual/reference/command/index.html
        @param command:
        @return:
        """
        return self.db.command(command)

    def create_index(self, coll_name, keys, unique=True):
        collection = self.get_collection(coll_name)
        _keys = [(key, pymongo.ASCENDING) for key in keys]
        collection.create_index(_keys, unique=unique)

    def get_index(self, coll_name):
        return self.get_collection(coll_name).index_information()

    def drop_collection(self, coll_name):
        return self.db.drop_collection(coll_name)

    def get_index_key(self, coll_name, index_name):
        """
        获取参与索引的key
        Args:
            index_name: 索引名

        Returns:

        """
        cache_key = f"{coll_name}:{index_name}"

        if cache_key in self.__index__cached:
            return self.__index__cached.get(cache_key)

        index = self.get_index(coll_name)
        index_detail = index.get(index_name)
        if not index_detail:
            errmsg = f"not found index {index_name} in collection {coll_name}"
            raise Exception(errmsg)

        index_keys = [val[0] for val in index_detail.get("key")]
        self.__index__cached[cache_key] = index_keys
        return index_keys

    def __get_update_condition(
            self, coll_name: str, data: dict, duplicate_errmsg: str
    ) -> dict:
        """
        根据索引冲突的报错信息 获取更新条件
        Args:
            duplicate_errmsg: E11000 duplicate key error collection: feapder.test index: a_1_b_1 dup key: { : 1, : "你好" }
            data: {"a": 1, "b": "你好", "c": "嘻嘻"}

        Returns: {"a": 1, "b": "你好"}

        """
        index_name = re.search(r"index: (\w+)", duplicate_errmsg).group(1)
        index_keys = self.get_index_key(coll_name, index_name)

        condition = {key: data.get(key) for key in index_keys}
        return condition


if __name__ == '__main__':
    mongo_url = 'mongodb://admin:admin_password@10.10.10.10:27017'
    mongo_db = MongoDB(host=mongo_url, db='test_db')
    mongo_db.add('test_tb', {'test_data': 'test_data'})
    pass


Python 连接 MongoDB 集群

Python 连接 MongoDB 的驱动为 pymongo, 基于 pymongo 有封装的 mongoengine,以及基于mongoengine 的 flask_mongoengie。

方法 1:使用 pymongo 连接 MongoDB 集群

示例代码:

from pymongo import MongoClient

# 创建 MongoDB 连接 URI
uri = "mongodb://username:password@hostname1:port1,hostname2:port2,hostname3:port3/?replicaSet=replica_set_name"

# 连接到 MongoDB
client = MongoClient(uri)

# 获取数据库和集合
db = client.your_database
collection = db.your_collection

# 执行操作(示例)
result = collection.find_one()
print(result)

说明:

  • username:MongoDB 6 的用户名
  • password:MongoDB 6 的密码
  • hostname1:port1,hostname2:port2,hostname3:port3:MongoDB 分片集群的主机名和端口号列表,以逗号分隔
  • replica_set_name:MongoDB 分片集群的副本集名称
  • your_database:要操作的数据库名称
  • your_collection:要操作的集合名称

示例代码 2:

建立了一个MongoDB集群,集群名称 replSet=rs0,包含以下 3 个节点:

172.16.250.233:27017 # SECONDARY
172.16.250.234:27017 # PRIMARY
172.16.250.237:27017 # SECONDARY

集群的 test 用户的密码为 “123456” ,只能访问 test 数据库。另外还有一个 MongoDB 数据库单独部署在 172.16.250.238,其 admin 用户的密码为 “123456” ,只能访问 admin 数据库。MongoDB 集群没有提供类似MySQL集群和Redis集群中的虚拟IP。在使用的时候需要客户端连接时指定MongoDB 集群的所有节点。

# coding=utf-8

from pymongo import MongoClient

# ################################ single mongo ##########################################
# ret : ['admin', 'config', 'local']
c = MongoClient(host="172.16.250.238", port=27017)
# c = MongoClient(host="mongodb://172.16.250.238:27017")
# c = MongoClient(host="mongodb://admin:123456@172.16.250.238:27017")
# c = MongoClient(host="mongodb://admin:123456@172.16.250.238:27017/admin")

# ################################ mongo cluster ##########################################
# ret : ['test']
mongodb_cluster_ip = '172.16.250.233:27017,172.16.250.234:27017,172.16.250.237:27017'
c = MongoClient(f'mongodb://test:123456@{mongodb_cluster_ip}/test')
# c = MongoClient(f'mongodb://test:123456@{mongodb_cluster_ip}/test?replicaSet=rs0')
# c = MongoClient(f'mongodb://test:123456@{mongodb_cluster_ip}/test?readPreference=secondary')

print(c.list_database_names())

方法 2:使用 mongoengine 连接 MongoDB 集群

示例代码:

# coding=utf-8

from mongoengine import connect
from mongoengine import Document
from mongoengine import StringField

# single mongo
connect('admin', host='mongodb://admin:123456@172.16.250.238:27017')


# mongo cluster
cluster_ip = '172.16.250.233:27017,172.16.250.234:27017,172.16.250.237:27017'
# connect('test', host=f'mongodb://test:123456@{cluster_ip}/test?readPreference=secondary')


class User(Document):  # 类名需要与数据库中的集合名称一致
    name = StringField(required=True, max_length=200)


users = User.objects.all()  # 返回所有的文档对象列表

for u in users:
    print("name:", u.name)
pass

方法 3:使用 flask_mongoengine 连接 MongoDB 集群

示例代码:

# coding=utf-8
from flask_mongoengine import MongoEngine
from flask import Flask

app = Flask(__name__)

# app.config['MONGODB_SETTINGS'] = {
#         'host': 'mongodb://admin:123456@172.16.250.238:27017/admin',
#         }

# app.config.from_pyfile('mongo.cfg')

# app.config['MONGODB_SETTINGS'] = {
#        'db': 'admin',
#        'username': 'admin',
#        'password': '123456',
#        'host': '172.16.250.238',
#        'port': 27017
#        }

app.config['MONGODB_SETTINGS'] = [
    {
        'db': 'test',
        'username': 'test',
        'password': '123456',
        'host': '172.16.250.233',
        'port': 27017
    },
    {
        'db': 'test',
        'username': 'test',
        'password': '123456',
        'host': '172.16.250.234',
        'port': 27017
    }, {
        'db': 'test',
        'username': 'test',
        'password': '123456',
        'host': '172.16.250.237',
        'port': 27017
    }
]

db = MongoEngine(app)


class User(db.Document):
    name = db.StringField(required=True, max_length=50)


users = User.objects.all()  # 返回所有的文档对象列表

for u in users:
    print("name:", u.name)

配置文件 mongo.cfg 格式如下:

MONGODB_SETTINGS = {
    'host': 'mongodb://admin:123456@172.16.250.238:27017/admin',
}

Python 操作 mongodb

首先引入包:pip install pymongo

需要用到如下对象:
    MongoClient 对象:用于与 MongoDB服务器建立连接
        client = MongoClient('主机ip',端口)
 
    DataBase 对象:对应着MongoDB中的数据库
        db = client.数据库名称

    Collection 对象:对应着MongoDB中的集合
        col = db.集合名称

    Cursor 对象:查询方法find()返回的对象,用于进行多行数据的遍历
        当调用集合对象的find()方法时,会返回Cursor对象
        结合for...in...遍历cursor对象

主要方法:
    insert_one:   加入一条文档对象
    insert_many:加入多条文档对象
    find_one:     查找一条文档对象
    find:            查找多条文档对象
    update_one:   更新一条文档对象
    update_many:更新多条文档对象
    delete_one:   删除一条文档对象
    delete_many:删除多条文档对象

插入方法:
    insert_one()     :传入一个字典,表示插入一个文档
    insert_many()  :传入一个列表,列表的元素为字典,插入多条文档

mongodb 的条件操作符

#    (>)    大于     - $gt
#    (<)    小于     - $lt
#    (>=)   大于等于 - $gte
#    (<= )  小于等于 - $lte

# 例:查询集合中 age 大于 25 的所有记录
for i in my_set.find({"age":{"$gt":25}}):
    print(i)

type(判断类型)
    
# 类型队对照列表
# Double    1     
# String    2     
# Object    3     
# Array    4     
# Binary data    5     
# Undefined    6    已废弃
# Object id    7     
# Boolean    8     
# Date    9     
# Null    10     
# Regular Expression    11     
# JavaScript    13     
# Symbol    14     
# JavaScript (with scope)    15     
# 32-bit integer    16     
# Timestamp    17     
# 64-bit integer    18     
# Min key    255    Query with -1.
# Max key    127     

# 找出 name 的类型是 String 的
for i in my_set.find({'name':{'$type':2}}):
    print(i)

排序:在MongoDB中使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,
      使用 1 和 -1 来指定排序的方式,其中 1 为升序,-1为降序。

for i in my_set.find().sort([("age",1)]):
    print(i)


limit 和 skip

# limit()方法用来读取指定数量的数据
# skip()方法用来跳过指定数量的数据
# 下面表示跳过两条数据后读取6条
for i in my_set.find().skip(2).limit(6):
    print(i)

IN 操作
# 找出 age 是 20、30、35 的数据
for i in my_set.find({"age":{"$in":(20,30,35)}}):
    print(i)


OR 操作
#找出age是20或35的记录
for i in my_set.find({"$or":[{"age":20},{"age":35}]}):
    print(i)


all 操作
'''
dic = {"name":"lisi","age":18,"li":[1,2,3]}
dic2 = {"name":"zhangsan","age":18,"li":[1,2,3,4,5,6]}

my_set.insert(dic)
my_set.insert(dic2)'''
for i in my_set.find({'li':{'$all':[1,2,3,4]}}):
    print(i)

# 查看是否包含全部条件
# 输出:{'_id': ObjectId('58c503b94fc9d44624f7b108'), 'name': 'zhangsan', 'age': 18, 'li': [1, 2, 3, 4, 5, 6]}

push / pushAll

my_set.update({'name':"lisi"}, {'$push':{'li':4}})
for i in my_set.find({'name':"lisi"}):
    print(i)
# 输出:{'li': [1, 2, 3, 4], '_id': ObjectId('58c50d784fc9d44ad8f2e803'), 'age': 18, 'name': 'lisi'}

my_set.update({'name':"lisi"}, {'$pushAll':{'li':[4,5]}})
for i in my_set.find({'name':"lisi"}):
    print(i)
# 输出:{'li': [1, 2, 3, 4, 4, 5], 'name': 'lisi', 'age': 18, '_id': ObjectId('58c50d784fc9d44ad8f2e803')}

pop/pull/pullAll

# pop
# 移除最后一个元素(-1为移除第一个)
my_set.update({'name':"lisi"}, {'$pop':{'li':1}})
for i in my_set.find({'name':"lisi"}):
    print(i)
# 输出:{'_id': ObjectId('58c50d784fc9d44ad8f2e803'), 'age': 18, 'name': 'lisi', 'li': [1, 2, 3, 4, 4]}

# pull (按值移除)
# 移除3
my_set.update({'name':"lisi"}, {'$pop':{'li':3}})

# pullAll (移除全部符合条件的)
my_set.update({'name':"lisi"}, {'$pullAll':{'li':[1,2,3]}})
for i in my_set.find({'name':"lisi"}):
    print(i)
# 输出:{'name': 'lisi', '_id': ObjectId('58c50d784fc9d44ad8f2e803'), 'li': [4, 4], 'age': 18}

插入:

insert()       insert 插入一个列表多条数据不用遍历,效率高
insert_one()   传入一个字典,表示插入一个文档
insert_many()  传入一个列表,列表的元素为字典,插入多条文档

save()         save 需要遍历列表,一个个插入。

                   ( 现在已经废弃 ) save 插入数据时,没有则插入,有则覆盖

replace_one()      save 已经被废弃. 使用 insert_one 或者 replace_one 代替 save

db.collection.replaceOne(
   <filter>,         # 过滤的条件
   <replacement>,    # 替换的 document
   {
     upsert: <boolean>,    # 当 upsert 为 true 时:如果没有匹配的则插入。如果有匹配的则替换。
     writeConcern: <document>
   }
)

db.restaurant.replaceOne(
    {name:"Pizza Rat's Pizzaria"},
    {"_id":4, name" : "Pizza Rat's Pizzaria", "Borough" : "Manhattan", "violations" : 8 },
    {upsert:true}
)

示例代码:

import pymongo

'''
插入方法:
    insert_one() 传入一个字典,表示插入一个文档
    insert_many() 传入一个列表,列表的元素为字典,插入多条文档
'''


def insert():
    try:
        # 1 创建连接对象

        mongodb_config = dict(
            host='127.0.0.1',
            port=27017,
            username='admin',
            password='xxxxxxxx',
        )
        client = pymongo.MongoClient(**mongodb_config)

        # 如果这个数据库不存在,就在内存中虚拟创建
        # 当在库里创建集合的时候,就会在物理真实创建这个数据库
        test_db = client.get_database('test_db')
        test_tb = test_db.get_collection('test_tb')
        test_db.test_demo.insert_one({"name": "zs", "age": 20})
        # 插入多条
        test_db.test_stu.insert_many([{"name": 1}, {"name": 2}])
    except Exception as e:
        print(e)


if __name__ == '__main__':
    insert()

执行结果:

查询:

  • find_one():返回满足条件的文档集中第一条数据,类型为字典。如果没有查询结果返回None。
  • find():返回满足条件的所有文档,类型为Cursor对象,可以使用 for...in 遍历,每项为字典对象。如果没有查询结果返一个空的Cursor对象。

db = pymongo.MongoClient()
db.get_database(db_name).get_collection(tb_name).find({}, {'_id': 1})
db[db_name][tb_name].find({'v_tag': {'$exists': False}},{'_id':1})
db[db_name][tb_name].find({'likes':0,'archive_view':0,'article_view':0})

示例代码:

from pymongo import *
'''
查询方法:
    find_one()返回满足条件的文档集中第一条数据,类型为字典
                如果没有查询结果返回None
    方法find()返回满足条件的所有文档,类型为Cursor对象,可以使用for...in遍历,每项为字典对象
            如果没有查询结果返一个空的Cursor对象
'''
def select():
    try:
        # 1 创建连接对象
        client = MongoClient(host="localhost", port=27017)
        # 2 获取数据库,
        # 如果这个数据库不存在,就在内存中虚拟创建
        # 当在库里创建集合的时候,就会在物理真实创建这个数据库
        db = client.demo    # 使用demo数据库
        # 从stu查询数据
        # 查询一条,返回一个字典,如果没有结果返回None
        res = db.stu.find_one({"age": 18})
        print(res)
        # 查询全部结果,返回一个Cursor可迭代对象,每一个元素是字典
        # 如果没有查询结果会返回一个空的Cursor对象
        res = db.stu.find({"age": {"$gt": 18}})
        print(res)
    except Exception as e:
        print(e)


if __name__ == '__main__':
    select()

示例 2:

from pymongo import MongoClient

db = MongoClient(host='127.0.0.1', port=27017)
my_set = db.get_database('test').get_collection('test')

# 查询全部
for i in my_set.find():
    print(i)

# 查询 name=king 的
for i in my_set.find({"name": "king"}):
    print(i)
print(my_set.find_one({"name": "king"}))

更新:

    update_one()    :修改满足条件的文档集中的第一条文档
    update_many()   :修改满足条件的文档集中的所有文档
    
    注意:使用 $set 操作符修改特定属性的值,否则会修改整个文档


my_set.update(
   <query>,     # 查询条件
   <update>,    # update 的对象和一些更新的操作符
   {
     upsert: <boolean>,          # 如果不存在update的记录,是否插入
     multi: <boolean>,           # 可选,mongodb 默认是 false, 只更新找到的第一条记录
     writeConcern: <document>    # 可选,抛出异常的级别。
   }
)

示例代码:

from pymongo import *
'''
修改方法:
    update_one()修改满足条件的文档集中的第一条文档
    update_many()修改满足条件的文档集中的所有文档
    注意:使用$set操作符修改特定属性的值,否则会修改整个文档
'''
def update():
    try:
        # 1 创建连接对象
        client = MongoClient(host="localhost", port=27017)
        # 2 获取数据库,
        # 如果这个数据库不存在,就在内存中虚拟创建
        # 当在库里创建集合的时候,就会在物理真实创建这个数据库
        db = client.demo    # 使用demo数据库
        # 修改数据
        # 修改第一条符合条件的数据,传入条件和修改结果
        db.stu.update_one({"age": 18},{"$set": {"age": 100}})  # 把年龄是18的第一条年龄改成100
        # 所有符合条件数据都修改
        # db.stu.update_many({"age": 18},{"$set": {"age": 100}}) # 年龄18的所有数据年龄改成100
    except Exception as e:
        print(e)


if __name__ == '__main__':
    update()

示例 2:

from pymongo import MongoClient

db = MongoClient(host='127.0.0.1', port=27017)
my_set = db.get_database('test').get_collection('test')

# 把上面插入数据的 age 改为 20
my_set.update(
    {"name": "king"}, 
    {'$set': {"age": 20}}
)

update_condition = {'$set': {'v_tag': 'test', 'v_stat': 'test'}}
update_one({'_id': v_id}, update_condition)

删除:

    delete_one()    :删除满足条件的文档集中第一条文档
    delete_many() :删除满足条件的所有文档

    注意:使用 $set 操作符修改特定属性的值,否则会修改整个文档

my_set.remove(
   <query>,     #(可选)删除的文档的条件
   {
     justOne: <boolean>,         #(可选)如果设为 true 或 1,则只删除一个文档
     writeConcern: <document>    #(可选)抛出异常的级别
   }
)

示例代码:

from pymongo import *
'''
删除方法:
    delete_one()删除满足条件的文档集中第一条文档
    delete_many()删除满足条件的所有文档
    注意:使用$set操作符修改特定属性的值,否则会修改整个文档
'''
def delete():
    try:
        # 1 创建连接对象
        client = MongoClient(host="localhost", port=27017)
        # 2 获取数据库,
        # 如果这个数据库不存在,就在内存中虚拟创建
        # 当在库里创建集合的时候,就会在物理真实创建这个数据库
        db = client.demo    # 使用demo数据库
        # 修改数据
        # 修改第一条符合条件的文档删除
        db.stu.delete_one({"age": 18})  # 把年龄是18的第一条文档删除
        # 所有符合条件数据都删除
        db.stu.delete_many({"age": 18}) # 年龄18的所有文档删除
    except Exception as e:
        print(e)


if __name__ == '__main__':
    delete()

示例 2:

from pymongo import MongoClient

db = MongoClient(host='127.0.0.1', port=27017)
my_set = db.get_database('test').get_collection('test')

# 删除 name=king 的全部记录
my_set.remove({'name': 'king'})

# 删除name=king的某个id的记录
t_id = my_set.find_one({"name":"king"})["_id"]
my_set.remove(t_id)

# 删除集合里的所有记录
db.users.remove()

案例:
        使用 python 向集合 t3 中插入1000 条文档,文档的属性包括 _id、name
        _id 的值为 0、1、2、3...999。name 的值为 'py0'、'py1'...
        查询显示出 _id 为 100 的整倍数的文档,如 100、200、300...,并将 name 输出

示例代码:

import pymongo
if __name__ == '__main__':
    try:
        # 1 获得连接对象
        client = pymongo.MongoClient(host="localhost", port=27017)
        # 2 获取数据库
        db = client.demo
        # 3 执行业务逻辑 数据库操作
        # 插入1000条数据

        for id in range(0,1000):
            db.t3.insert_one({"_id": id, "name": "py%s"% id})

        # 取出符合条件的数据
        match = {
            "$where": "function(){return this._id%100 == 0 }",
            }
        res = db.t3.find(match, {"_id": 0, "name": 1})
        for info in res:
            print(info)


    except Exception as e:
        print(e)

示例代码:

import pymongo
from pymongo import MongoClient

client = MongoClient('localhost',27017)
#client = MongoClient('mongodb://localhost:27017')


# 访问数据库。当前所使用的数据库test的users
db = client.test
users = db.users
#或者db = client['users']


# 插入文档。文档就是一行,集合就是一个表。
# 一个insert_one()
user1 = {"name":"li8","age":8}
rs = users.insert_one(user1)
print('one insert:{0}'.format(rs.inserted_id))

# 多个 insert_many()
user2 = {"name":"li9","age":9}
user3 = {"name":"li10","age":10}
user4 = {"name":"li11","age":11}
user5 = {"name":"li12","age":12}
new_result = users.insert_many([user2, user3, user4, user5])
print('Multiple users: {0}'.format(new_result.inserted_ids))


# 检索文档
# find_one() 查询一个结果。
usertmp = users.find_one({"age":33})
print(usertmp)

# find() 查询多个结果。
result = users.find({'age': 33})
for tmp in result:
    print(tmp)


# 高级查询
result = users.find({'age':{"$lt":30}}).sort("name")
for tmp in result:
    print(tmp)


# 统计数量
print(users.count())

# 加索引
from pymongo import ASCENDING, DESCENDING
print(users.create_index([("age", DESCENDING), ("name", ASCENDING)]))

# 数据导出
mongoexport -d test -c users --csv -f name,age  -o e:\python\users.csv

多级 路径 元素操作

先插入一条数据
dic = {
    "name": "zhangsan",
    "age": 18,
    "contact": {
        "email": "1234567@qq.com",
        "iphone": "11223344"}
}
my_set.insert(dic)

# 多级目录用 "." 连接
for i in my_set.find({"contact.iphone":"11223344"}):
    print(i)
# 输出:{'name': 'zhangsan', '_id': ObjectId('58c4f99c4fc9d42e0022c3b6'), 'age': 18, 'contact': {'email': '1234567@qq.com', 'iphone': '11223344'}}

result = my_set.find_one({"contact.iphone":"11223344"})
print(result["contact"]["email"])
# 输出:1234567@qq.com

# 多级路径下修改操作
result = my_set.update({"contact.iphone":"11223344"},{"$set":{"contact.email":"9999999@qq.com"}})
result1 = my_set.find_one({"contact.iphone":"11223344"})
print(result1["contact"]["email"])
# 输出:9999999@qq.com

还可以对数组用索引操作
dic = {
    "name": "lisi",
    "age": 18,
    "contact": [
        {"email": "111111@qq.com", "iphone": "111"},
        {"email": "222222@qq.com", "iphone": "222"}
    ]
}
my_set.insert(dic)

# 查询
result1 = my_set.find_one({"contact.1.iphone":"222"})
print(result1)
# 输出:{'age': 18, '_id': ObjectId('58c4ff574fc9d43844423db2'), 'name': 'lisi', 'contact': [{'iphone': '111', 'email': '111111@qq.com'}, {'iphone': '222', 'email': '222222@qq.com'}]}

# 修改
result = my_set.update({"contact.1.iphone":"222"},{"$set":{"contact.1.email":"222222@qq.com"}})
print(result1["contact"][1]["email"])
# 输出:222222@qq.com

示例代码 :

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pymongo import MongoClient

settings = {
    "ip":'192.168.0.113',     # ip
    "port":27017,             # 端口
    "db_name" : "mydb",       # 数据库名字
    "set_name" : "test_set"   # 集合名字
}

class MyMongoDB(object):
    def __init__(self):
        try:
            self.conn = MongoClient(settings["ip"], settings["port"])
        except Exception as e:
            print(e)
        self.db = self.conn[settings["db_name"]]
        self.my_set = self.db[settings["set_name"]]

    def insert(self,dic):
        print("inser...")
        self.my_set.insert(dic)

    def update(self,dic,newdic):
        print("update...")
        self.my_set.update(dic,newdic)

    def delete(self,dic):
        print("delete...")
        self.my_set.remove(dic)

    def db_find(self,dic):
        print("find...")
        data = self.my_set.find(dic)
        for result in data:
            print(result["name"],result["age"])

def main():
    dic={"name":"zhangsan","age":18}
    mongo = MyMongoDB()
    mongo.insert(dic)
    mongo.db_find({"name":"zhangsan"})

    mongo.update({"name":"zhangsan"}, {"$set":{"age":"25"}})
    mongo.db_find({"name":"zhangsan"})

    mongo.delete({"name":"zhangsan"})
    mongo.db_find({"name":"zhangsan"})

if __name__ == "__main__":
    main()

示例代码 :

# encoding:utf=8
import pymongo

connection = pymongo.Connection('127.0.0.1', 27017)

db = connection.my_db   # 选择 my_db 库
tb = db.my_set          # 使用 my_set 集合

# 添加单条数据到集合中
user = {"name": "king", "age": "23"}
tb.insert(user)  # 添加数据
tb.save(user)   # 添加数据

# 同时添加多条数据到集合中
users = [
    {"name": "king_1", "age": "23"},
    {"name": "king_2", "age": "20"}
]
tb.insert(users)  # 添加数据
tb.save(users)  # 添加数据

# 删除命令如下:
tb.remove({"name": "king_1"})

# 修改命令如下:
# tb.update(xxxx)

# 查询命令如下:
# 查询单条记录
print(tb.find_one())

# 查询所有记录
for data in tb.find():
    print(data)

# 查询此集合中数据条数
print(tb.count())

# 简单参数查询
for data in tb.find({"name": "1"}):
    print(data)

# 使用find_one获取一条记录
print(tb.find_one({"name": "1"}))

示例代码 :

# -*-coding:utf8-*-
import pymongo

conn = pymongo.MongoClient()
tdb = conn.t_db
ttb = tdb.t_tb

data_1 = {'name': '孙悟空', 'age': 108000, 'skill': '让你们被猴打过'}
data_2 = {'name': '玉皇大帝', 'age': 36000, 'skill': 'creat anything', 'other': 'fuck thank you'}
data_3 = {'name': '如来', 'age': 'unknown', 'other': '送你上西天'}
ttb.insert(data_1)
ttb.insert(data_2)
ttb.insert(data_3)
ttb.remove({'name': '孙悟空'})
print('操作数据库完成!')

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python操作MongoDB增删改查方法如下: 1. 连接MongoDB数据库 使用pymongo库连接MongoDB数据库,代码如下: ```python import pymongo client = pymongo.MongoClient("mongodb://localhost:27017/") db = client["mydatabase"] ``` 2. 插入数据 使用insert_one()或insert_many()方法向MongoDB数据库中插入一条或多条数据,代码如下: ```python # 插入单条数据 mycollection = db["customers"] mydict = { "name": "John", "address": "Highway 37" } x = mycollection.insert_one(mydict) # 插入多条数据 mylist = [ { "name": "Amy", "address": "Apple st 652"}, { "name": "Hannah", "address": "Mountain 21"}, { "name": "Michael", "address": "Valley 345"}, { "name": "Sandy", "address": "Ocean blvd 2"}, { "name": "Betty", "address": "Green Grass 1"}, { "name": "Richard", "address": "Sky st 331"} ] x = mycollection.insert_many(mylist) ``` 3. 询数据 使用find()方法MongoDB数据库中的数据,代码如下: ```python # 询所有数据 for x in mycollection.find(): print(x) # 询指定数据 myquery = { "address": "Park Lane 38" } mydoc = mycollection.find(myquery) for x in mydoc: print(x) ``` 4. 更新数据 使用update_one()或update_many()方法更新MongoDB数据库中的数据,代码如下: ```python # 更新单条数据 myquery = { "address": "Valley 345" } newvalues = { "$set": { "address": "Canyon 123" } } mycollection.update_one(myquery, newvalues) # 更新多条数据 myquery = { "address": { "$regex": "^S" } } newvalues = { "$set": { "name": "Minnie" } } x = mycollection.update_many(myquery, newvalues) ``` 5. 除数据 使用delete_one()或delete_many()方法MongoDB数据库中的数据,代码如下: ```python # 除单条数据 myquery = { "address": "Mountain 21" } mycollection.delete_one(myquery) # 除多条数据 myquery = { "address": {"$regex": "^S"} } x = mycollection.delete_many(myquery) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值