MongoDB入门

  • MongoDB是一种流行的NoSQL数据库系统,它使用了灵活的文档导向的模型来存储和管理数据。与传统的关系数据库管理系统(RDBMS)不同,MongoDB不需要固定的表结构,它允许数据记录在没有预先定义模式的情况下被存储。这意味着数据库的记录可以有不同的字段,这对于处理大量异构数据非常有用。
  • MongoDB的数据结构类似于JSON对象,其格式称为BSON(Binary JSON),这种格式支持更丰富的数据类型。MongoDB提供了强大的查询语言,支持复杂的查询、索引、聚合操作等。它还具有高可扩展性,可以通过分片等技术实现水平扩展,支持大规模的数据存储和处理。
  • MongoDB最初是用C++语言编写的。C++以其性能优势和系统级编程能力被广泛用于开发数据库系统,这使得MongoDB可以高效地处理数据操作和内存管理。尽管MongoDB的核心是用C++编写的,但它也支持多种语言的驱动,例如Python、Java、Node.js等,开发者可以使用这些驱动在不同的应用程序中与MongoDB交互。
  • MongoDB 文档

核心特点

  1. 文档导向
    • MongoDB是基于文档的,这意味着它管理的基本数据单元是文档,这些文档类似于JSON对象,使得数据的读写非常直观。
    • 文档可以嵌套复杂的数据类型,如数组和文档。
  2. 动态模式
    • 数据可以在没有固定结构的情况下被存储,这给应对不断变化的数据结构带来了极大的灵活性。
  3. 可扩展性
    • MongoDB支持水平扩展,通过分片可以分布数据到多个服务器。
    • 复制集确保数据的高可用性和冗余。
  4. 强大的查询语言
    • 它支持丰富的查询操作,包括文档和字段级别的查询,以及正则表达式等。
  5. 索引优化
    • 支持多种类型的索引,以优化查询速度,包括地理空间索引、全文索引等。
  6. 聚合管道
    • MongoDB的聚合框架提供了一个功能丰富的数据处理管道,允许数据在多个阶段进行处理和转换。
  7. 格外的驱动支持
    • 有多种编程语言的官方支持,如Python、Java、C#、Node.js、Ruby等。
  8. 存储过程
    • 支持JavaScript编写的服务器端函数。
  9. 灵活的部署
    • MongoDB可以在多种环境中运行,包括云平台服务。
  10. 丰富的资源
    • MongoDB社区非常活跃,提供大量的资源和支持,从而简化了开发和维护的工作。
  11. 强大的交易支持
    • 尽管是NoSQL数据库,MongoDB也支持多文档事务,类似于关系型数据库的ACID事务。
  1. 访问MongoDB的官方下载中心。
  2. 选择"Windows"作为操作系统,选择所需版本,然后点击"下载"。
  3. 运行下载的 .msi 安装程序,并跟随提示进行安装。
  4. 完成安装后,可以将MongoDB的安装目录添加到系统的PATH环境变量中,以便在任何命令行窗口中运行MongoDB。
  5. 你还需要手动创建一个数据库存储目录(默认是 C:\data\db)。
  6. 启动MongoDB服务。在命令行中运行 mongod。
  7. 要开始使用MongoDB,你可以在另一个命令行窗口中运行 mongo 来启动 MongoDB Shell。
  1. 对于macOS,可以使用Homebrew来安装MongoDB。如果还没有安装Homebrew,请先安装它。
  2. 打开终端。
  3. 运行 brew tap mongodb/brew 来添加MongoDB的官方Homebrew tap。
  4. 然后运行 brew install mongodb-community@7.0 来安装最新版本的MongoDB。
  5. 通过 brew services start mongodb-community@7.0 命令启动MongoDB服务。
  6. 使用 mongo 命令来连接MongoDB服务并打开MongoDB Shell。

对于Linux,安装步骤将因发行版本不同而有所变化。以下是基于Ubuntu的安装步骤:

  1. 导入MongoDB公钥。这样可以确保deb软件包的一致性和真实性。
    1
    2
    3
    curl -fsSL https://pgp.mongodb.com/server-7.0.asc | \
    sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg \
    --dearmor
  2. 创建列表文件
    1
    echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.com/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
  3. 重新加载本地包数据库
    1
    sudo apt-get update
  4. 安装MongoDB
    1
    sudo apt-get install -y mongodb-org
  5. 启动MongoDB服务
    1
    sudo systemctl start mongod
  6. 如果你想MongoDB随系统启动而自动运行,使用
    1
    sudo systemctl enable mongod
  7. 连接到MongoDB
    1
    mongo

MySQL与 MongoDB 对比

MySQL MongoDB
database db(数据库)
table collection(集合)
一条数据 document(文档)

MongoDB 之 db 操作

  • 创建数据库

    MongoDB中并不需要显式创建数据库。当你首次向数据库中的集合(collection)插入一条文档(document)时,MongoDB会自动创建这个数据库。

    1
    2
    use myNewDatabase             // 切换到名为myNewDatabase的数据库,如果不存在,则准备创建
    db.myNewCollection.insertOne({a: 1}) // 向名为myNewCollection的集合插入一个文档,这将自动创建数据库和集合
  • 选择数据库

    使用 use 命令加上数据库名来选择数据库。

    1
    use myDatabase  // 切换到名为myDatabase的数据库
  • 查看当前数据库

    要查看当前选定的数据库,你可以使用 db 命令。

    1
    db  // 显示当前数据库
  • 列出所有数据库

    使用 show dbs 命令列出服务器上的所有数据库。

    1
    show dbs  // 列出所有可用的数据库
  • 删除数据库

    要删除当前选中的数据库,可以使用 db.dropDatabase() 命令。

    1
    2
    use myOldDatabase  // 首先切换到你想要删除的数据库
    db.dropDatabase() // 删除当前选中的数据库
  • 其他数据库级别的操作

    • 查看数据库状态:db.stats()
    • 创建用户:db.createUser()
    • 查看数据库中的集合:show collections
    • 备份数据库:使用mongodump工具
    • 恢复数据库:使用mongorestore工具

MongoDB 之 collection 操作

  • 查看所有集合

    要查看当前数据库中的所有集合,可以使用 show collections 命令。

    1
    show collections

    在 MongoDB 中,运行此命令会列出当前选定数据库中的所有集合的名称。

  • 创建集合

    虽然 MongoDB 会在你第一次向集合插入文档时自动创建集合,但如果你需要创建一个具有特定选项(例如固定大小或索引)的集合,可以使用 db.createCollection() 方法来显式创建它。

    1
    db.createCollection("myNewCollection")

    你还可以传递一个选项对象来指定其它属性,例如设置集合为固定大小。

    1
    db.createCollection("myCappedCollection", { capped: true, size: 100000 })

    在这个例子中,myCappedCollection 是一个固定大小的集合,其大小上限是100,000字节。

  • 删除集合

    • 使用 db.collection.drop() 方法来删除一个集合。
      1
      db.myOldCollection.drop()
    • 这条命令将会删除名为 myOldCollection 的集合。如果操作成功,它将返回 true;如果你尝试删除一个不存在的集合,它将返回 false。
    • 注意:删除集合是不可逆的,并且会同时删除集合中的所有文档。

MongoDB 之 document 操作

  • 插入文档

    • 插入单个文档

      使用 insertOne 方法来插入一个文档到指定的集合中。如果集合不存在,MongoDB会自动创建这个集合。

      1
      2
      3
      4
      5
      db.collectionName.insertOne({
      name: "John Doe",
      age: 30,
      email: "johndoe@example.com"
      })

      这个命令会在 collectionName 集合中插入一个包含 name、age 和 email 字段的文档。

    • 插入多个文档

      使用 insertMany 方法插入多个文档到集合中。这个方法接收一个文档数组作为参数。

      1
      2
      3
      4
      db.collectionName.insertMany([
      { name: "Jane Doe", age: 25, email: "janedoe@example.com" },
      { name: "Jim Beam", age: 35, email: "jimbeam@example.com" }
      ])

      这个命令会在 collectionName 集合中插入两个文档。

    • 附加说明

      • 在MongoDB中,每个插入的文档都会自动赋予一个 _id 字段,这是文档的唯一标识符。如果在插入文档时没有提供 _id 字段,MongoDB会自动生成一个ObjectId类型的 _id 字段。
      • 插入文档后,MongoDB会返回一个结果对象,其中包含关于操作的信息,比如影响的文档数和文档的 _id 等。
      • 例如,插入单个文档后的返回结果可能类似这样:
        1
        2
        3
        4
        {
        "acknowledged" : true,
        "insertedId" : ObjectId("5f50c31e1c4ae8635237f460")
        }
      • 同样,使用 insertMany 插入多个文档时,你会得到每个被插入文档的 _id 的列表。
      • 请注意,文档的字段可以是各种数据类型,不仅限于字符串或数字,还可以是数组、另一个文档或者甚至是二进制数据等。
  • 查询文档

    • 查询所有文档

      使用 find() 方法不带任何参数就可以查询集合中的所有文档。

      1
      db.collectionName.find()

      这会显示 collectionName 集合中的所有文档。

    • 查询特定文档

      添加查询条件作为 find() 方法的参数,可以查询满足特定条件的文档。

      1
      db.collectionName.find({ age: { $gt: 25 } })

      这个命令会查询 collectionName 集合中 age 大于25的所有文档。

    • 查询并返回特定字段

      如果你只需要文档中的特定字段,可以在 find() 方法中指定第二个参数来包含或排除字段。

      1
      db.collectionName.find({}, { name: 1, age: 1, _id: 0 })

      这个命令会返回 collectionName 集合中所有文档的 name 和 age 字段,并排除 _id 字段。

    • 查询单个文档

      使用 findOne() 方法可以返回满足查询条件的第一个文档。

      1
      db.collectionName.findOne({ name: "John Doe" })

      这个命令会查询 collectionName 集合中第一个名字为"John Doe"的文档。

    • 使用查询操作符

      查询操作符可以提供更强大的查询功能,如范围查询、正则表达式查询等。

      1
      db.collectionName.find({ age: { $lte: 30 } })

      这个命令会查询 collectionName 集合中 age 小于或等于30的所有文档。

    • 多条件查询

      • $and

        $and 操作符可以连接多个查询条件,只有同时满足所有条件的文档才会被查询到

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        # 查询年龄大于等于20且名字为"John"的文档
        results = collection.find({
        "$and": [
        {"age": {"$gte": 20}},
        {"name": "John"}
        ]
        })

        for document in results:
        print(document)

      • $or

        $or 操作符至少满足其中一个条件的文档都会被查询到

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        # 查询名字为"John"或年龄小于30的文档
        results = collection.find({
        "$or": [
        {"name": "John"},
        {"age": {"$lt": 30}}
        ]
        })

        for document in results:
        print(document)

      • $nor

        $nor 操作符用来查询不满足任何条件的文档

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        # 查询年龄不大于20且名字不为"John"的文档
        results = collection.find({
        "$nor": [
        {"age": {"$gt": 20}},
        {"name": "John"}
        ]
        })

        for document in results:
        print(document)

      • $not

        $not 操作符用来查询不满足指定条件的文档

        1
        2
        3
        4
        5
        6
        7
        8
        # 查询名字不以字母"J"开头的文档
        results = collection.find({
        "name": {"$not": {"$regex": "^J"}}
        })

        for document in results:
        print(document)

      • 组合 $and 与 $or

        你也可以在同一个查询中组合使用$and和$or

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        # 查询年龄大于20且名字为"John"或者年龄小于30的文档(注意优先级和分组)
        results = collection.find({
        "$and": [
        {
        "$or": [
        {"name": "John"},
        {"age": {"$lt": 30}}
        ]
        },
        {"age": {"$gt": 20}}
        ]
        })

        for document in results:
        print(document)

    • 排序查询结果

      使用 sort() 方法对查询结果进行排序。

      1
      db.collectionName.find().sort({ age: -1 })

      这个命令会返回 collectionName 集合中的所有文档,结果按 age 字段降序排序。

    • 限制查询结果数量

      使用 limit() 方法限制查询结果的数量。

      1
      db.collectionName.find().limit(5)

      这个命令会返回 collectionName 集合中的前5个文档。

    • 跳过指定数量的文档

      使用 skip() 方法跳过查询结果中的指定数量的文档。

      1
      db.collectionName.find().skip(5)

      这个命令会跳过 collectionName 集合中的前5个文档,并返回之后的文档。

    • 链式使用查询方法

      find() 方法返回的是一个游标,你可以链式调用 sort()、limit() 和 skip() 方法。

      1
      db.collectionName.find().sort({ age: 1 }).limit(5).skip(10)

      这个命令会查询 collectionName 集合,跳过前10个文档,然后按 age 升序排序,并且只返回接下来的5个文档。

  • 更新文档

    • 更新单个文档

      使用 updateOne 方法可以更新满足条件的第一个文档。你需要提供一个查询条件和要更新的字段。

      1
      2
      3
      4
      db.collectionName.updateOne(
      { name: "John Doe" },
      { $set: { email: "john.doe@newdomain.com" } }
      )

      这个命令会在 collectionName 集合中查找第一个名为"John Doe"的文档,并更新其 email 字段。

    • 更新多个文档

      使用 updateMany 方法可以更新所有满足条件的文档。

      1
      2
      3
      4
      db.collectionName.updateMany(
      { age: { $gt: 30 } },
      { $set: { status: "senior" } }
      )

      这个命令会更新 collectionName 集合中所有 age 大于30的文档,为他们添加或更新 status 字段为 “senior”。

    • 替换文档

      使用 replaceOne 方法可以替换满足条件的第一个文档。

      1
      2
      3
      4
      db.collectionName.replaceOne(
      { name: "John Doe" },
      { name: "John Doe", age: 50, status: "senior" }
      )

      这个命令会在 collectionName 集合中查找第一个名为 “John Doe” 的文档,并完全替换它(除了 _id 字段,除非你显式地也替换了它)。

    • 原子操作符

      MongoDB提供一系列原子操作符来更新文档,如 $set 用于设置字段值,$inc 用于增加字段值,$push 用于数组字段添加元素等。

      1
      2
      3
      4
      db.collectionName.updateOne(
      { name: "Jane Doe" },
      { $inc: { age: 1 } }
      )

      这个命令会将 collectionName 集合中名为 “Jane Doe” 的文档的 age 字段增加1。

    • 更新文档的选项

      updateOne 和 updateMany 方法还接受额外的选项参数。例如,如果你想在没有匹配文档时插入一个新文档,可以使用 upsert 选项。

      1
      2
      3
      4
      5
      db.collectionName.updateOne(
      { name: "New User" },
      { $set: { age: 30, status: "new" } },
      { upsert: true }
      )

      如果找不到名为 “New User” 的文档,上面的命令将插入一个新文档。

    • 注意事项

      • 更新操作默认只作用于第一个匹配的文档(updateOne和replaceOne);如果你需要更新多个文档,则应使用updateMany。
      • 更新操作不会修改文档的 _id 值。
      • 如果更新命令导致文档字段的减少,那么这些字段将被删除。
      • 使用 updateMany 时要特别小心,因为它会更新所有匹配的文档。
  • 删除文档

    • 删除单个文档

      使用 deleteOne 方法删除满足条件的第一个文档。

      1
      db.collectionName.deleteOne({ name: "John Doe" })

      这个命令会在 collectionName 集合中删除第一个名字为 “John Doe” 的文档。

    • 删除多个文档

      使用 deleteMany 方法删除所有满足条件的文档。

      1
      db.collectionName.deleteMany({ status: "inactive" })

      这个命令会删除 collectionName 集合中所有 status 字段为 “inactive” 的文档。

    • 删除所有文档

      要删除集合中的所有文档,可以传递一个空的查询对象给 deleteMany 方法。

      1
      db.collectionName.deleteMany({})

      这会删除 collectionName 集合中的所有文档。请注意,这不会删除集合本身。

    • 注意事项

      • 在执行删除操作之前,请确保你有充分的备份,以防止数据丢失。
      • 考虑到安全性,MongoDB不允许无条件删除集合中的所有文档;必须提供一个空的查询对象 {} 以指明你确实打算删除所有文档。
      • 删除操作是不可逆的,一旦执行,被删除的文档将无法恢复。
      • 对于大规模的删除操作,可能需要考虑对性能的影响,以及是否要在非高峰时段执行。
  • 计数文档

    • 使用 countDocuments()

      这个方法提供了一个准确的文档数量,基于查询过滤器。

      1
      db.collectionName.countDocuments({ status: "active" })

      以上命令会返回 collectionName 集合中状态为 “active” 的文档数量。

    • 使用 estimatedDocumentCount()

      这个方法提供了一个估算值,这通常更快,但不会考虑任何查询过滤器。

      1
      db.collectionName.estimatedDocumentCount()

      以上命令会返回 collectionName 集合中的估算文档数量。

    • 注意事项

      • countDocuments() 实际上会执行一个查询,并且对结果进行计数,因此如果集合很大且有复杂的查询条件,这可能会比较慢。
      • estimatedDocumentCount() 方法基于集合的元数据迅速返回一个估算值,这个数字可能不会包括最近的集合更改,如果最近没有发生写入操作,那么这个方法返回结果非常快,适用于较大的数据集。
      • countDocuments() 和 estimatedDocumentCount() 在返回结果时的性能差异通常在于是否使用索引和集合的大小。
  • 排序文档

    • 排序单个字段

      例如,如果你想要按照名字升序排序:

      1
      db.collectionName.find().sort({ name: 1 })

      如果你想要按照名字降序排序:

      1
      db.collectionName.find().sort({ name: -1 })
    • 排序多个字段

      如果你想要按照多个字段进行排序,比如先按照年龄升序排序,如果年龄相同再按照名字升序排序:

      1
      db.collectionName.find().sort({ age: 1, name: 1 })
    • 使用索引进行排序

      为了提高排序操作的效率,尤其是在处理大数据集时,你应该考虑使用索引。如果排序的字段上有索引,MongoDB将能够更高效地进行排序操作。

    • 注意事项

      • 对于大量数据的排序操作,如果没有合适的索引,排序可能非常耗时。
      • 在没有索引支持的情况下,MongoDB将所有文档加载到内存中进行排序。如果处理的数据量超过了系统的可用内存,这将导致性能问题。
      • 如果排序操作耗尽了MongoDB的排序操作内存限制(默认是32MB),查询将会失败。你可以通过创建索引或增加内存限制来解决这个问题。
  • 限制查询结果

    • 限制查询结果

      例如,如果你只想获取5个文档,你可以这样做:

      1
      db.collectionName.find().limit(5)

      这个命令会返回 collectionName 集合中的前5个文档。

    • 结合排序和限制

      你还可以结合使用排序和限制,比如,如果你想获取分数最高的5个学生:

      1
      db.collectionName.find().sort({ score: -1 }).limit(5)

      这将会按分数降序排序后,返回前5个文档。

    • 结合跳过和限制以进行分页

      如果你想实现分页效果,你可以结合使用 skip() 和 limit() 方法。例如,如果每页显示5个文档,并且你想获取第二页的文档:

      1
      db.collectionName.find().skip(5).limit(5)

      这里,skip(5) 会跳过前5个文档,即第一页的内容,而 limit(5) 则限制了只返回5个文档,即第二页的内容。

    • 注意事项

      • 使用 limit() 方法可以避免发送太多的数据给客户端,这对于性能和带宽都是一个好处。
      • sort() , skip() , 和 limit() 方法的组合通常用于实现分页功能,但请注意 skip() 操作在大数据集合中可能会导致性能问题,因为它仍然需要遍历所有被跳过的文档。
      • 对于更高效的分页,特别是在处理大量数据时,可以考虑使用范围查询(range queries)来代替 skip()。

PyMongo 之 document 操作

  • 插入文档

    • 插入单个文档

      要插入单个文档到MongoDB集合中,可以使用 insert_one() 方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      # 定义要插入的单个文档
      my_document = {
      "name": "John Doe",
      "age": 30,
      "address": "123 Elm Street"
      }

      # 执行插入操作
      insert_result = collection.insert_one(my_document)

      # 打印插入文档的ID
      print(f"Inserted document with id: {insert_result.inserted_id}")

    • 插入多个文档

      如果你想一次性插入多个文档,可以使用 insert_many() 方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      # 定义要插入的多个文档
      my_documents = [
      {"name": "Jane Doe", "age": 25, "address": "456 Maple Street"},
      {"name": "Alice Johnson", "age": 28, "address": "789 Oak Street"},
      {"name": "Bob Smith", "age": 32, "address": "101 Pine Street"}
      ]

      # 执行插入操作
      insert_result = collection.insert_many(my_documents)

      # 打印插入文档的ID列表
      print(f"Inserted documents with ids: {insert_result.inserted_ids}")

    • 说明

      • 当使用 insert_one() 或 insert_many() 方法时,PyMongo会自动在每个文档中添加一个 _id 字段,用作该文档的唯一标识。如果文档中已经包含了 _id 字段,则PyMongo将使用该值作为文档的标识。
      • 在执行插入操作后,insert_one() 和 insert_many() 方法都会返回一个结果对象,该对象包含了插入操作的信息,例如 inserted_id 或 inserted_ids 属性,它们分别代表插入的单个文档的ID或多个文档的ID列表。
  • 查询文档

    • 查询单个文档

      使用 find_one() 方法来查询单个文档。如果有多个文档匹配查询条件,find_one() 将返回第一个匹配的文档。

      1
      2
      3
      # 查询名字为"John Doe"的第一个文档
      document = collection.find_one({'name': 'John Doe'})
      print(document)
    • 查询多个文档

      使用 find() 方法来查询多个文档。find() 返回一个可迭代的游标对象,可以遍历集合中所有匹配的文档。

      1
      2
      3
      4
      5
      6
      7
      # 查询所有文档
      for doc in collection.find():
      print(doc)

      # 查询所有名字为"John Doe"的文档
      for doc in collection.find({'name': 'John Doe'}):
      print(doc)
    • 使用查询操作符

      MongoDB 提供了多种查询操作符,例如 $lt (小于), $gt (大于), $eq (等于), 等等,来精细化查询条件。

      1
      2
      3
      # 查询年龄大于25的所有文档
      for doc in collection.find({'age': {'$gt': 25}}):
      print(doc)
    • 限制查询结果数目

      你可以结合使用 limit() 方法来限制查询结果的数目。

      1
      2
      3
      # 查询年龄大于25,但仅返回前两个文档
      for doc in collection.find({'age': {'$gt': 25}}).limit(2):
      print(doc)
    • 指定返回的字段

      使用 projection 参数来指定返回的字段。

      1
      2
      3
      # 只返回name和age字段
      for doc in collection.find({}, {'name': 1, 'age': 1, '_id': 0}):
      print(doc)

      在这里,1 表示包含字段,0 表示排除字段。_id 字段默认是包含的,除非明确排除。

    • 排序查询结果

      可以使用 sort() 方法对查询结果进行排序。

      1
      2
      3
      4
      5
      6
      7
      # 按年龄升序排序
      for doc in collection.find().sort('age', pymongo.ASCENDING):
      print(doc)

      # 按年龄降序排序
      for doc in collection.find().sort('age', pymongo.DESCENDING):
      print(doc)
    • find_one_and_delete

      这个方法查找并删除一个文档。它返回被删除的文档。

      1
      2
      3
      4
      5
      # 查找并删除名字为"John Doe"的第一个文档
      deleted_document = collection.find_one_and_delete({'name': 'John Doe'})

      # 输出被删除的文档
      print(deleted_document)
    • find_one_and_replace

      这个方法查找一个文档并用另一个文档替换它。它返回原始文档,或者如果设置了 return_document 参数,则返回更新后的文档。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 查找名字为"John Doe"的第一个文档,并用新的文档替换它
      new_document = {'name': 'John Doe', 'age': 30, 'address': '123 Park Ave'}
      replaced_document = collection.find_one_and_replace(
      {'name': 'John Doe'},
      new_document,
      return_document=pymongo.ReturnDocument.AFTER
      )

      # 输出替换后的文档
      print(replaced_document)
    • find_one_and_update

      这个方法查找一个文档并更新它。可以指定更新的具体操作,比如使用 $set 来修改字段。它返回原始文档,或者如果设置了 return_document 参数,则返回更新后的文档。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 查找名字为"John Doe"的第一个文档,并更新它的年龄
      updated_document = collection.find_one_and_update(
      {'name': 'John Doe'},
      {'$set': {'age': 29}},
      return_document=pymongo.ReturnDocument.AFTER
      )

      # 输出更新后的文档
      print(updated_document)

  • 更新文档

    • 更新单个文档

      使用 update_one() 方法来更新单个文档。你需要提供一个查询条件(用于找到需要更新的文档)和一个更新操作符(如 $set 用于指定更新的字段和值)。

      1
      2
      3
      4
      5
      # 更新名字为"John Doe"的第一个匹配文档的年龄
      result = collection.update_one({'name': 'John Doe'}, {'$set': {'age': 29}})

      # 输出被更新文档的数量
      print(f"Documents updated: {result.modified_count}")
    • 更新多个文档

      使用 update_many() 方法来更新多个文档。和 update_one() 使用相同的查询条件和更新操作符,但会更新所有匹配的文档。

      1
      2
      3
      4
      5
      # 更新所有名字为"John Doe"的文档的地址
      result = collection.update_many({'name': 'John Doe'}, {'$set': {'address': '123 Main Street'}})

      # 输出被更新文档的数量
      print(f"Documents updated: {result.modified_count}")
    • 原子操作符

      除了 $set 之外,还可以使用其他的原子操作符,比如 $inc 用于增加数值字段,或 $push 用于向数组字段添加元素。

      1
      2
      3
      4
      5
      6
      7
      # 将名为"John Doe"的文档的"visit_count"字段增加1
      result = collection.update_one({'name': 'John Doe'}, {'$inc': {'visit_count': 1}})
      print(f"Documents updated: {result.modified_count}")

      # 向名为"John Doe"的文档的"tags"数组添加一个新元素
      result = collection.update_one({'name': 'John Doe'}, {'$push': {'tags': 'new-tag'}})
      print(f"Documents updated: {result.modified_count}")
    • upsert 操作

      如果你想在更新操作中进行 “upsert”(如果文档不存在则插入),你可以设置 upsert=True。

      1
      2
      3
      4
      5
      # 如果找不到则插入新文档
      result = collection.update_one({'name': 'Eve Adams'}, {'$set': {'age': 30}}, upsert=True)
      print(f"Documents matched: {result.matched_count}")
      print(f"Documents modified: {result.modified_count}")
      print(f"Upserted ID: {result.upserted_id}")

      如果查询条件没有匹配任何文档,并且 upsert=True,则MongoDB将插入一个包含查询条件和更新操作指定字段的新文档。

  • 删除文档

    • 删除单个文档

      使用 delete_one() 方法可以删除一个与查询条件匹配的文档。如果有多个文档匹配,只有第一个会被删除。

      1
      2
      3
      4
      5
      # 删除名字为"John Doe"的第一个匹配文档
      delete_result = collection.delete_one({'name': 'John Doe'})

      # 输出被删除文档的数量
      print(f"Documents deleted: {delete_result.deleted_count}")
    • 删除多个文档

      使用 delete_many() 方法可以删除所有匹配查询条件的文档。

      1
      2
      3
      4
      5
      # 删除所有名字为"John Doe"的文档
      delete_result = collection.delete_many({'name': 'John Doe'})

      # 输出被删除文档的数量
      print(f"Documents deleted: {delete_result.deleted_count}")
    • 删除所有文档

      如果你想删除集合中的所有文档,可以传递一个空的查询对象给 delete_many() 方法。

      1
      2
      3
      4
      5
      # 警告:这将删除集合中的所有文档
      delete_result = collection.delete_many({})

      # 输出被删除文档的数量
      print(f"All documents deleted: {delete_result.deleted_count}")

      请注意,在执行删除操作时要特别小心,因为这些操作是不可逆的。对于生产环境中的数据,通常建议先执行查询确认需要删除的文档,然后再进行删除操作。同时,定期备份数据库是一种好的习惯,以防止数据丢失。

  • 排序文档

    • 基本排序

      你可以使用 sort() 方法来定义排序的字段和方向。使用 pymongo.ASCENDING 作为升序,pymongo.DESCENDING 作为降序。

      1
      2
      3
      4
      5
      6
      7
      8
      # 升序排序
      documents = collection.find().sort('fieldname', pymongo.ASCENDING)

      # 降序排序
      documents = collection.find().sort('fieldname', pymongo.DESCENDING)

      for document in documents:
      print(document)
    • 多字段排序

      如果你想根据多个字段进行排序,可以向 sort() 方法传递一个包含多个元组的列表,每个元组包含字段名称和方向。

      1
      2
      3
      4
      5
      6
      7
      8
      # 根据多个字段进行排序,例如先按 age 升序,然后按 name 降序
      documents = collection.find().sort([
      ('age', pymongo.ASCENDING),
      ('name', pymongo.DESCENDING)
      ])

      for document in documents:
      print(document)
    • 使用链式调用进行排序

      在 PyMongo 中,可以通过对查询结果进行链式调用来进行多步骤的数据处理,包括排序。

      1
      2
      3
      4
      5
      # 链式调用:先筛选年龄大于25的文档,然后按年龄升序排序
      documents = collection.find({'age': {'$gt': 25}}).sort('age', pymongo.ASCENDING)

      for document in documents:
      print(document)
  • 计数文档

    在PyMongo中,你可以使用 count_documents() 方法来准确地统计满足特定查询条件的文档数量。如果你只需要一个大致的估计值,也可以使用 estimated_document_count() 方法,它基于集合的元数据信息快速给出一个近似的文档数量。

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

    # 连接到MongoDB
    client = MongoClient('mongodb://localhost:27017/')

    # 选择数据库和集合
    db = client['your_database']
    collection = db['your_collection']

    # 使用count_documents来计数满足条件的文档数量
    # 例如,计数年龄大于20的文档
    count = collection.count_documents({'age': {'$gt': 20}})
    print("Number of documents where age is greater than 20:", count)

    # 如果你想计数集合中所有的文档,可以传递一个空的查询对象
    total_count = collection.count_documents({})
    print("Total number of documents in the collection:", total_count)

    # 使用estimated_document_count来快速估计集合中的文档总数
    # 注意这不会应用任何过滤条件,并且可能不是完全准确的
    estimated_count = collection.estimated_document_count()
    print("Estimated total number of documents in the collection:", estimated_count)

查询条件操作符

操作符 描述 示例
$eq 等于(equal to) {'age': {'$eq': 30}} 匹配年龄等于30的文档
$gt 大于(greater than) {'age': {'$gt': 30}} 匹配年龄大于30的文档
$gte 大于等于(greater than or equal to) {'age': {'$gte': 30}} 匹配年龄大于等于30的文档
$lt 小于(less than) {'age': {'$lt': 30}} 匹配年龄小于30的文档
$lte 小于等于(less than or equal to) {'age': {'$lte': 30}} 匹配年龄小于等于30的文档
$ne 不等于(not equal to) {'age': {'$ne': 30}} 匹配年龄不等于30的文档
$in 在给定数组里(in) {'age': {'$in': [25, 30, 35]}} 匹配年龄为25, 30或35的文档
$nin 不在给定数组里(not in) {'age': {'$nin': [25, 30, 35]}} 匹配年龄不为25, 30或35的文档
$or 或条件(logical OR) {'$or': [{'age': 20}, {'name': 'John'}]} 匹配年龄为20或名字为John的文档
$and 与条件(logical AND) {'$and': [{'age': {'$gt': 20}}, {'name': 'John'}]} 匹配年龄大于20并且名字为John的文档
$not 非条件(logical NOT) {'age': {'$not': {'$lt': 30}}} 匹配年龄不小于30的文档
$exists 字段是否存在 {'name': {'$exists': True}} 匹配包含name字段的文档
$regex 正则表达式 {'name': {'$regex': '^J'}} 匹配名字以"J"开头的文档
$type 类型检查 {'age': {'$type': 'int'}} 匹配年龄字段类型为integer的文档
  • 安装 PyMongo

    1
    pip install pymongo
  • 连接到 MongoDB

    1
    2
    3
    4
    from pymongo import MongoClient

    # 创建MongoDB客户端连接对象
    client = MongoClient('mongodb://localhost:27017/')

    如果 MongoDB 运行在不同的主机或端口上,你需要相应地调整连接字符串。

  • 选择数据库和集合

    连接到指定的数据库和集合:

    1
    2
    3
    4
    5
    # 选择数据库
    db = client['my_database']

    # 选择集合
    collection = db['my_collection']

    确保将 'my_database' 和 'my_collection' 替换为实际的数据库和集合名称。

  • 插入文档

    插入一个或多个文档到集合中:

    1
    2
    3
    4
    5
    6
    7
    8
    # 插入单个文档
    result = collection.insert_one({'name': 'Alice', 'age': 30})

    # 插入多个文档
    results = collection.insert_many([
    {'name': 'Bob', 'age': 25},
    {'name': 'Charlie', 'age': 35}
    ])
  • 查询文档

    查询集合中的文档:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 查询单个文档
    user = collection.find_one({'name': 'Alice'})

    # 查询所有匹配的文档
    users = collection.find({'age': {'$gt': 25}})

    for user in users:
    print(user)

    其中 '$gt' 是一个查询操作符,意味着“大于”。

  • 更新文档

    更新集合中的一个或多个文档:

    1
    2
    3
    4
    5
    # 更新单个文档
    result = collection.update_one({'name': 'Alice'}, {'$set': {'age': 31}})

    # 更新多个文档
    results = collection.update_many({'age': {'$gt': 25}}, {'$inc': {'age': 1}})

    这里 '$set' 操作符用于设定字段的值,'$inc' 用于增加一个值。

  • 删除文档

    从集合中删除一个或多个文档:

    1
    2
    3
    4
    5
    # 删除单个文档
    result = collection.delete_one({'name': 'Bob'})

    # 删除多个文档
    results = collection.delete_many({'age': {'$lt': 30}})

    其中 '$lt' 是一个查询操作符,意味着“小于”。

  • 索引

    在集合上创建索引以提高查询效率:

    1
    2
    # 在'name'字段上创建索引
    index_result = collection.create_index([('name', pymongo.ASCENDING)])
  • 关闭连接

    在所有操作完成后,关闭客户端连接:

    1
    client.close()
  • 综合示例

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    from pymongo import MongoClient

    # 假设你已经安装了pymongo: pip install pymongo

    # 连接MongoDB,假设MongoDB在本地运行,默认端口27017
    client = MongoClient('mongodb://localhost:27017/')

    # 选择数据库'mydatabase',如果它不存在,将在第一次插入数据时自动创建
    db = client['mydatabase']

    # 选择集合(相当于关系数据库的表)'users'
    collection = db['users']

    # 插入一个文档(相当于关系数据库的记录)
    user1 = {'name': 'Alice', 'age': 25}
    collection.insert_one(user1)

    # 插入多个文档
    users = [
    {'name': 'Bob', 'age': 30},
    {'name': 'Charlie', 'age': 35}
    ]
    collection.insert_many(users)

    # 查询单个文档
    print(collection.find_one({'name': 'Alice'}))

    # 查询所有文档
    for user in collection.find():
    print(user)

    # 更新文档
    collection.update_one({'name': 'Alice'}, {'$set': {'age': 26}})

    # 删除文档
    collection.delete_one({'name': 'Bob'})

    # 创建索引
    collection.create_index([('name', 1)])

    # 关闭MongoDB连接
    client.close()

    这个脚本演示了以下操作:

    1. 连接到本地运行的 MongoDB 实例。
    2. 选择或创建一个名为 mydatabase 的数据库。
    3. 选择或创建一个名为 users 的集合。
    4. 向 users 集合中插入一个单独的文档。
    5. 向 users 集合中插入多个文档。
    6. 执行查询以寻找名为 “Alice” 的文档。
    7. 遍历并打印出 users 集合中的所有文档。
    8. 更新名为 “Alice” 的文档的年龄。
    9. 删除名为 “Bob” 的文档。
    10. 在 name 字段上创建一个索引以提高查询性能。
    11. 关闭与 MongoDB 的连接。

友情链接

本文结束 感谢您的阅读
正在加载今日诗词....