-
基础匹配查询:
*|------------------------------------------|
|{ "id_card": "134353387483947" }
| -
确认某字段是否存在
-
查询所有存在age字段:
|-----------------------------------------------|
|db.users.find({age: {$exists: true}})
| -
查询所有不存在age字段:
|-------------------------------------------------|
|db.users.find({name: {$exists: false}})
|
-
-
多表关联查询:
-
可以使用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配置方式如图:
- 索引【A 】数量为3,【B】数量为5,全连接返回了两个索引的全部数量的记录数8,每条记录都包含A+B的全部数据;
- 参考链接:MongoDB的分组操作,联集合查询(多表查询)_mongodb 命令多个表union-CSDN博客
-
-
在 MongoDB 索引设计中,某些文档的特定字段存在,而另一些文档该字段不存在时,选择将缺失字段设为
null
还是直接不包含该字段,取决于以下几点考虑:-
查询性能
-
字段不存在 :当文档中字段缺失时,MongoDB 在查询中会视该字段为"不存在"。如果你经常使用
{ field: { $exists: true } }
查询,MongoDB 会在索引中记录哪些文档包含该字段,不需要扫描全部数据。 -
字段设为
null
:如果你将不存在的字段显式设置为null
,你可以直接通过{ field: null }
查询相关文档。在某些情况下(如需要与现有字段null
值保持一致),使用null
可能会更方便
-
-
索引大小
-
字段不存在:当字段不存在时,索引将不记录该字段。这样索引的大小会相对较小。如果你的文档中大量字段是缺失的,选择不包含该字段可以减少索引的大小和数据库的存储开销。
-
字段设为
null
:如果将不存在的字段设为null
,这些文档会被包含在索引中,增加索引的大小。不过,如果null
是有效的查询条件或需要在某些查询中明确区分"无值"和"缺失",使用null
更有意义。
-
-
查询复杂性
-
字段不存在 :如果你明确区分"字段缺失"和"字段值为 null",那么可以使用
$exists
或类似的查询操作。这样有助于区分那些根本没有该字段的文档和字段值为null
的文档,减少查询的歧义性 -
字段设为
null
:如果你希望在查询中将"缺失字段"和"字段值为 null"的情况视为相同,使用null
会让查询更简单和一致,因为你可以直接通过{ field: null }
查找。
-
-
数据一致性
-
如果业务逻辑上不存在字段也被视为"没有值",可以考虑使用
null
,这能在数据结构上保持一致性,让查询和数据处理更直观。 -
如果需要严格区分"没有这个字段"和"字段值为空",可以选择让字段不存在。
-
-
总结建议
-
如果你希望通过索引减少存储和加快查询速度 ,并且能够通过
$exists
等条件处理字段缺失,推荐 不包含字段。 -
如果查询逻辑中需要统一处理"缺失字段"和"字段为空" ,并且希望在查询中简化操作,推荐将缺失字段 设置为
null
。 -
选择哪种方式取决于你的具体查询需求和数据模型设计。
-
-
-
在 MongoDB 中,当字段不存在 或 字段值设为null 时,查询性能可能会受到哪些影响,以下是相关的几点分析:
-
索引的行为
-
字段不存在 :如果文档中没有某个字段,而你对该字段建立了索引,MongoDB 的索引只会记录那些拥有该字段的文档。如果你进行查询时使用了
{ field: { $exists: true } }
,MongoDB 通过索引可以快速找到包含该字段的文档。然而,如果你使用{ field: { $exists: false } }
,这种查询无法通过索引快速获取结果,因为它需要扫描整个集合来找出哪些文档不包含该字段。 -
字段设为
null
:如果你将不存在的字段显式设为null
,查询{ field: null }
将直接使用索引查找所有值为null
的文档,效率较高。这种方式减少了全表扫描的概率。
-
-
查询性能差异
-
存在字段(
exists: true
)查询:这种查询可以使用索引,性能通常较好,尤其是当索引覆盖大量文档时。查询会直接从索引中找到哪些文档包含该字段,减少全表扫描。 -
不存在字段(
exists: false
)查询:如果查询条件是找出那些没有某个字段的文档,则可能需要进行全表扫描,因为索引中只记录了存在字段的文档,而 MongoDB 无法从索引中直接查出"缺失字段"的文档。这种情况下,性能可能比查找有字段的文档要差一些,特别是在集合规模较大时。
-
-
索引优化
-
稀疏索引 :如果某个字段在文档中并非总是存在,可以使用 稀疏索引 (
sparse: true
)来仅为那些包含该字段的文档建立索引。稀疏索引不包括字段缺失的文档,因此在查询包含字段的文档时,可以提高效率。然而,稀疏索引对于查询缺失字段的文档($exists: false
)仍然需要全表扫描。 -
复合索引:在多字段查询时,如果某个字段有时存在、有时不存在,可以设计复合索引。比如将一个常见字段与一个稀疏字段结合在一起的复合索引,可能能够帮助优化部分查询。
-
-
MongoDB 查询优化
- MongoDB 会在查询时尽量利用现有的索引和缓存来优化性能。如果字段不存在,MongoDB 可能不得不执行全表扫描,从而导致查询速度变慢。在这种情况下,如果查询涉及大量字段缺失的文档,使用显式
null
值可能更高效,因为 MongoDB 可以通过索引快速识别这些文档。
- MongoDB 会在查询时尽量利用现有的索引和缓存来优化性能。如果字段不存在,MongoDB 可能不得不执行全表扫描,从而导致查询速度变慢。在这种情况下,如果查询涉及大量字段缺失的文档,使用显式
-
总结:
-
如果你的查询主要查找字段存在的文档,字段缺失不会明显影响性能,尤其是使用了合适的索引。
-
如果你的查询频繁查找字段不存在的文档(
exists: false
),则这种查询无法直接利用索引,性能可能下降。考虑通过稀疏索引或调整数据模型来优化。 -
如果查询场景对"字段缺失"和"字段为空"的区分不敏感,可以考虑使用
null
代替缺失字段,简化查询并提高查询性能。 -
因此,查询是否存在该字段的性能差异取决于你的索引结构和查询模式。
-
-
-
如果最终为了减少存储和加快查询速度,选择空值字段不存在的形式设计索引,那么查询query如下:
-
查询字段存在且有特定值
-
如果你希望查询某个字段存在且包含特定值的文档,可以使用以下查询语法:
|------------------------------------------------------------------------------|
|db.collection.find({ fieldName: { $exists: true, $eq: "keyword" } })
|这条查询语句表示:
fieldName: { $exists: true }:确保该字段存在。
$eq: "keyword":确保该字段的值等于 "keyword"。
-
-
查询字段缺失的文档
-
如果要查询字段不存在的文档,可以使用
$exists
操作符:|---------------------------------------------------------------|
|db.collection.find({ fieldName: { $exists: false } })
|这条查询语句会返回所有 不包含 fieldName 字段 的文档。
-
-
查询字段存在且不为
null
-
如果你需要查询某个字段存在,并且它的值不是
null
或其他空值的情况,可以这样写:|-------------------------------------------------------------------------|
|db.collection.find({ fieldName: { $exists: true, $ne: null } })
|这条查询语句返回包含该字段且该字段的值不为
null
的文档。
-
-
全文搜索特定字段
-
如果你想对某个字段进行关键字匹配(例如部分匹配),可以使用
$regex
来进行模糊匹配:|---------------------------------------------------------------------------------|
|db.collection.find({ fieldName: { $exists: true, $regex: /keyword/ } })
|这条查询语句会查找所有
fieldName
包含keyword
的文档,注意这是正则表达式匹配。
-
-
总结
如果字段值为空时选择该字段不存在,那么查询该字段内容时通常需要加上
$exists: true
的条件,确保查询只会返回那些包含该字段的文档。例如:|---------------------------------------------------------------------------------|
|db.collection.find({ fieldName: { $exists: true, $regex: /keyword/ } })
|这样可以确保只查询存在该字段并且匹配指定内容的文档。
-
Mongodb学习记录
yingchenwy2024-10-16 14:33