本文演示如何组合使用 $exists (检查字段是否存在) 和 $ne (不等于) 来查找「字段存在且值不为空字符串」的文档。
创建示例数据(包含各种边界情况)
> db.existsDemo.insertOne({"Name":"Chris","Age":21});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd7c3916d78f205348bc650") }
> db.existsDemo.insertOne({"Name":"","Age":null});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd7c39a6d78f205348bc651") }
> db.existsDemo.insertOne({"Name":null,"Age":24});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd7c3a66d78f205348bc652") }
> db.existsDemo.insertOne({"Age":23});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd7c3c36d78f205348bc653") }
显示所有数据
> db.existsDemo.find().pretty();
{ "_id" : ObjectId("5cd7c3916d78f205348bc650"), "Name" : "Chris", "Age" : 21 }
{ "_id" : ObjectId("5cd7c39a6d78f205348bc651"), "Name" : "", "Age" : null }
{ "_id" : ObjectId("5cd7c3a66d78f205348bc652"), "Name" : null, "Age" : 24 }
{ "_id" : ObjectId("5cd7c3c36d78f205348bc653"), "Age" : 23 }
查询:Name 字段存在 ($exists: true) 且 不为空字符串 ($ne: "")
> db.existsDemo.find({
"$and": [
{ "Name": { "$exists": true } },
{ "Name": { "$ne": "" } }
]
});
结果
{ "_id" : ObjectId("5cd7c3916d78f205348bc650"), "Name" : "Chris", "Age" : 21 }
{ "_id" : ObjectId("5cd7c3a66d78f205348bc652"), "Name" : null, "Age" : 24 }
结果分析
| 文档 | Name 值 | $exists: true | $ne: "" | 最终结果 |
|---|---|---|---|---|
| Chris | "Chris" | ✅ | ✅ | ✅ 匹配 |
| 空字符串 | "" | ✅ | ❌ | ❌ |
| null | null | ✅ | ✅ (null ≠ "") | ✅ 匹配 |
| 字段不存在 | (无) | ❌ | - | ❌ |
重要区别
$exists: true- 字段在文档中存在(值可以是 null, "", 0, false 等)$ne: ""- 值不等于空字符串(null 也满足,因为 null ≠ "")- 组合后:字段存在 且 不为空字符串(允许 null)
常见变体需求
// 1. 字段存在且不为 null 且不为空字符串
{ $and: [
{ Name: { $exists: true } },
{ Name: { $ne: null } },
{ Name: { $ne: "" } }
]}
// 2. 字段存在且为非空字符串 (排除 null)
{ Name: { $type: "string", $ne: "" } }
// 3. 字段不存在或为空字符串
{ $or: [
{ Name: { $exists: false } },
{ Name: "" }
]}
// 4. 使用 $expr (Aggregation 语法在 Query 中)
{ $expr: { $and: [ { $ne: ["$Name", ""] }, { $ne: ["$Name", null] } ] } }
索引提示
对 Name 创建索引可加速此类查询,但 $exists 和 $ne 的索引使用效率取决于选择性。