Mongodb学习记录

  1. 基础匹配查询:
    *

    |------------------------------------------|
    | { "id_card": "134353387483947" } |

  2. 确认某字段是否存在

    1. 查询所有存在age字段:

      |-----------------------------------------------|
      | db.users.find({age: {$exists: true}}) |

    2. 查询所有不存在age字段:

      |-------------------------------------------------|
      | db.users.find({name: {$exists: false}}) |

  3. 多表关联查询:

    • 可以使用aggregation+lookup 实现类似mysql的左连接 查询,再综合unionWith 实现类似mysql的全连接查询;

    • 【左连接】参考语法:

      |---------------------------------------------------------------------------------------------------------------------------------------------|
      | [ { $lookup: { from: "B", localField: "id_card", foreignField: "id_card", as: "自测指标" } }, { $match: { "自测指标.rbc.value": "4.6" } } ] |

      • 如使用mongodb compass,配置方式如右图:
    • 【左连接+右连接】实现【全连接】查询语法:

      |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
      | db.collectionA.aggregate([ // Left join collectionA with collectionB { $lookup: { from: "collectionB", localField: "fieldA", foreignField: "fieldB", as: "leftJoinResult" } }, // Union with the right join result { $unionWith: { coll: "collectionB", pipeline: [ { $lookup: { from: "collectionA", localField: "fieldB", foreignField: "fieldA", as: "rightJoinResult" } }, // Optionally, format or reshape the rightJoinResult documents ] } }, // Optional: Further operations such as grouping to handle duplicates ]); |

    • 使用mongodb compass配置方式如图:

      1. 索引【A 】数量为3,【B】数量为5,全连接返回了两个索引的全部数量的记录数8,每条记录都包含A+B的全部数据;
      2. 参考链接:MongoDB的分组操作,联集合查询(多表查询)_mongodb 命令多个表union-CSDN博客
  4. 在 MongoDB 索引设计中,某些文档的特定字段存在,而另一些文档该字段不存在时,选择将缺失字段设为 null 还是直接不包含该字段,取决于以下几点考虑:

    1. 查询性能

      1. 字段不存在 :当文档中字段缺失时,MongoDB 在查询中会视该字段为"不存在"。如果你经常使用 { field: { $exists: true } } 查询,MongoDB 会在索引中记录哪些文档包含该字段,不需要扫描全部数据。

      2. 字段设为 null :如果你将不存在的字段显式设置为 null,你可以直接通过 { field: null } 查询相关文档。在某些情况下(如需要与现有字段 null 值保持一致),使用 null 可能会更方便

    2. 索引大小

      1. 字段不存在:当字段不存在时,索引将不记录该字段。这样索引的大小会相对较小。如果你的文档中大量字段是缺失的,选择不包含该字段可以减少索引的大小和数据库的存储开销。

      2. 字段设为 null :如果将不存在的字段设为 null,这些文档会被包含在索引中,增加索引的大小。不过,如果 null 是有效的查询条件或需要在某些查询中明确区分"无值"和"缺失",使用 null 更有意义。

    3. 查询复杂性

      1. 字段不存在 :如果你明确区分"字段缺失"和"字段值为 null",那么可以使用 $exists 或类似的查询操作。这样有助于区分那些根本没有该字段的文档和字段值为 null 的文档,减少查询的歧义性

      2. 字段设为 null :如果你希望在查询中将"缺失字段"和"字段值为 null"的情况视为相同,使用 null 会让查询更简单和一致,因为你可以直接通过 { field: null } 查找。

    4. 数据一致性

      1. 如果业务逻辑上不存在字段也被视为"没有值",可以考虑使用 null,这能在数据结构上保持一致性,让查询和数据处理更直观。

      2. 如果需要严格区分"没有这个字段"和"字段值为空",可以选择让字段不存在。

    5. 总结建议

      1. 如果你希望通过索引减少存储和加快查询速度 ,并且能够通过 $exists 等条件处理字段缺失,推荐 不包含字段

      2. 如果查询逻辑中需要统一处理"缺失字段"和"字段为空" ,并且希望在查询中简化操作,推荐将缺失字段 设置为 null

      3. 选择哪种方式取决于你的具体查询需求和数据模型设计。

  5. 在 MongoDB 中,当字段不存在 或 字段值设为null 时,查询性能可能会受到哪些影响,以下是相关的几点分析:

    1. 索引的行为

      1. 字段不存在 :如果文档中没有某个字段,而你对该字段建立了索引,MongoDB 的索引只会记录那些拥有该字段的文档。如果你进行查询时使用了 { field: { $exists: true } },MongoDB 通过索引可以快速找到包含该字段的文档。然而,如果你使用 { field: { $exists: false } },这种查询无法通过索引快速获取结果,因为它需要扫描整个集合来找出哪些文档不包含该字段。

      2. 字段设为 null :如果你将不存在的字段显式设为 null,查询 { field: null } 将直接使用索引查找所有值为 null 的文档,效率较高。这种方式减少了全表扫描的概率。

    2. 查询性能差异

      1. 存在字段(exists: true)查询:这种查询可以使用索引,性能通常较好,尤其是当索引覆盖大量文档时。查询会直接从索引中找到哪些文档包含该字段,减少全表扫描。

      2. 不存在字段(exists: false)查询:如果查询条件是找出那些没有某个字段的文档,则可能需要进行全表扫描,因为索引中只记录了存在字段的文档,而 MongoDB 无法从索引中直接查出"缺失字段"的文档。这种情况下,性能可能比查找有字段的文档要差一些,特别是在集合规模较大时。

    3. 索引优化

      1. 稀疏索引 :如果某个字段在文档中并非总是存在,可以使用 稀疏索引sparse: true)来仅为那些包含该字段的文档建立索引。稀疏索引不包括字段缺失的文档,因此在查询包含字段的文档时,可以提高效率。然而,稀疏索引对于查询缺失字段的文档($exists: false)仍然需要全表扫描。

      2. 复合索引:在多字段查询时,如果某个字段有时存在、有时不存在,可以设计复合索引。比如将一个常见字段与一个稀疏字段结合在一起的复合索引,可能能够帮助优化部分查询。

    4. MongoDB 查询优化

      1. MongoDB 会在查询时尽量利用现有的索引和缓存来优化性能。如果字段不存在,MongoDB 可能不得不执行全表扫描,从而导致查询速度变慢。在这种情况下,如果查询涉及大量字段缺失的文档,使用显式 null 值可能更高效,因为 MongoDB 可以通过索引快速识别这些文档。
    5. 总结:

      1. 如果你的查询主要查找字段存在的文档,字段缺失不会明显影响性能,尤其是使用了合适的索引。

      2. 如果你的查询频繁查找字段不存在的文档(exists: false),则这种查询无法直接利用索引,性能可能下降。考虑通过稀疏索引或调整数据模型来优化。

      3. 如果查询场景对"字段缺失"和"字段为空"的区分不敏感,可以考虑使用 null 代替缺失字段,简化查询并提高查询性能。

      4. 因此,查询是否存在该字段的性能差异取决于你的索引结构和查询模式。

  6. 如果最终为了减少存储和加快查询速度,选择空值字段不存在的形式设计索引,那么查询query如下:

    1. 查询字段存在且有特定值

      1. 如果你希望查询某个字段存在且包含特定值的文档,可以使用以下查询语法:

        |------------------------------------------------------------------------------|
        | db.collection.find({ fieldName: { $exists: true, $eq: "keyword" } }) |

        这条查询语句表示:

        fieldName: { $exists: true }:确保该字段存在。

        $eq: "keyword":确保该字段的值等于 "keyword"。

    2. 查询字段缺失的文档

      1. 如果要查询字段不存在的文档,可以使用 $exists 操作符:

        |---------------------------------------------------------------|
        | db.collection.find({ fieldName: { $exists: false } }) |

        这条查询语句会返回所有 不包含 fieldName 字段 的文档。

    3. 查询字段存在且不为 null

      1. 如果你需要查询某个字段存在,并且它的值不是 null 或其他空值的情况,可以这样写:

        |-------------------------------------------------------------------------|
        | db.collection.find({ fieldName: { $exists: true, $ne: null } }) |

        这条查询语句返回包含该字段且该字段的值不为 null 的文档。

    4. 全文搜索特定字段

      1. 如果你想对某个字段进行关键字匹配(例如部分匹配),可以使用 $regex 来进行模糊匹配:

        |---------------------------------------------------------------------------------|
        | db.collection.find({ fieldName: { $exists: true, $regex: /keyword/ } }) |

        这条查询语句会查找所有 fieldName 包含 keyword 的文档,注意这是正则表达式匹配。

    5. 总结

      如果字段值为空时选择该字段不存在,那么查询该字段内容时通常需要加上 $exists: true 的条件,确保查询只会返回那些包含该字段的文档。例如:

      |---------------------------------------------------------------------------------|
      | db.collection.find({ fieldName: { $exists: true, $regex: /keyword/ } }) |

      这样可以确保只查询存在该字段并且匹配指定内容的文档。

相关推荐
数据的世界011 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐1 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
梦想平凡1 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
TianyaOAO2 小时前
mysql的事务控制和数据库的备份和恢复
数据库·mysql
Ewen Seong2 小时前
mysql系列5—Innodb的缓存
数据库·mysql·缓存
码农老起2 小时前
企业如何通过TDSQL实现高效数据库迁移与性能优化
数据库·性能优化
夏木~3 小时前
Oracle 中什么情况下 可以使用 EXISTS 替代 IN 提高查询效率
数据库·oracle
W21553 小时前
Liunx下MySQL:表的约束
数据库·mysql
黄名富3 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
言、雲3 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库