Amazon DocumentDB 高级查询 #

一、复杂条件查询 #

1.1 嵌套逻辑组合 #

javascript
// 复杂的AND/OR组合
db.users.find({
  $and: [
    {
      $or: [
        { role: "admin" },
        { role: "superuser" }
      ]
    },
    {
      $or: [
        { status: "active" },
        { lastLogin: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) } }
      ]
    }
  ]
})

1.2 条件表达式 #

javascript
// 使用$expr进行字段间比较
db.products.find({
  $expr: {
    $gt: ["$price", "$cost"]
  }
})

// 字段间运算
db.orders.find({
  $expr: {
    $gt: [
      { $multiply: ["$quantity", "$price"] },
      1000
    ]
  }
})

1.3 条件分支 #

javascript
// 使用$cond进行条件判断
db.sales.aggregate([
  {
    $project: {
      name: 1,
      amount: 1,
      status: {
        $cond: {
          if: { $gte: ["$amount", 1000] },
          then: "high",
          else: "normal"
        }
      }
    }
  }
])

二、数组高级操作 #

2.1 数组元素查询 #

javascript
// 查询数组中特定条件的元素
db.users.find({
  scores: { $elemMatch: { $gt: 80, $lt: 90 } }
})

// 嵌套对象数组查询
db.users.find({
  education: {
    $elemMatch: {
      school: "清华大学",
      degree: "本科"
    }
  }
})

// 多条件数组查询
db.products.find({
  variants: {
    $elemMatch: {
      color: "red",
      size: "L",
      stock: { $gt: 0 }
    }
  }
})

2.2 数组长度查询 #

javascript
// 查询数组长度
db.users.find({ tags: { $size: 3 } })

// 查询数组长度大于某值(需要聚合)
db.users.aggregate([
  {
    $addFields: {
      tagsCount: { $size: "$tags" }
    }
  },
  {
    $match: {
      tagsCount: { $gt: 3 }
    }
  }
])

2.3 数组操作符 #

javascript
// $all - 包含所有元素
db.articles.find({
  tags: { $all: ["mongodb", "database", "nosql"] }
})

// $elemMatch - 元素匹配
db.students.find({
  grades: {
    $elemMatch: {
      subject: "数学",
      score: { $gte: 90 }
    }
  }
})

// 数组索引查询
db.users.find({ "tags.0": "编程" })  // 第一个元素
db.users.find({ "tags.1": "阅读" })  // 第二个元素

2.4 数组更新后查询 #

javascript
// 使用$定位操作符
db.users.find(
  { "grades.subject": "数学" },
  { "grades.$": 1 }
)

// 使用$elemMatch投影
db.students.find(
  { name: "张三" },
  {
    grades: {
      $elemMatch: { score: { $gte: 90 } }
    }
  }
)

三、正则表达式高级用法 #

3.1 复杂正则匹配 #

javascript
// 多条件正则
db.users.find({
  $or: [
    { email: { $regex: /^[a-z]+@example\.com$/i } },
    { phone: { $regex: /^1[3-9]\d{9}$/ } }
  ]
})

// 正则组合
db.products.find({
  name: { $regex: /^(iPhone|iPad|Mac)/ }
})

// 排除模式
db.users.find({
  email: { $not: { $regex: /test@/ } }
})

3.2 正则选项 #

javascript
// 不区分大小写
db.users.find({
  name: { $regex: /zhang/i }
})

// 多行模式
db.articles.find({
  content: { $regex: /^Title/m }
})

// 使用$options
db.users.find({
  email: {
    $regex: "^[a-z]+@example\\.com$",
    $options: "i"
  }
})

3.3 性能考虑 #

text
正则查询性能:
├── 前缀匹配可以使用索引(/^prefix/)
├── 其他正则无法使用索引
├── 大数据量正则查询可能很慢
└── 考虑使用文本索引替代

四、地理空间查询 #

4.1 地理空间索引 #

javascript
// 创建2dsphere索引
db.locations.createIndex({ location: "2dsphere" })

// 创建2d索引
db.places.createIndex({ coords: "2d" })

4.2 附近查询 #

javascript
// 查找附近的点
db.locations.find({
  location: {
    $near: {
      $geometry: {
        type: "Point",
        coordinates: [116.4074, 39.9042]  // 经度, 纬度
      },
      $maxDistance: 1000,  // 最大距离(米)
      $minDistance: 0
    }
  }
})

// 使用$nearSphere(球面距离)
db.locations.find({
  location: {
    $nearSphere: {
      $geometry: {
        type: "Point",
        coordinates: [116.4074, 39.9042]
      },
      $maxDistance: 5000
    }
  }
})

4.3 范围查询 #

javascript
// 圆形范围
db.locations.find({
  location: {
    $geoWithin: {
      $centerSphere: [
        [116.4074, 39.9042],  // 圆心
        5 / 6371  // 半径(弧度)
      ]
    }
  }
})

// 多边形范围
db.locations.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [[
          [116.0, 39.0],
          [117.0, 39.0],
          [117.0, 40.0],
          [116.0, 40.0],
          [116.0, 39.0]
        ]]
      }
    }
  }
})

4.4 GeoJSON类型 #

javascript
// Point
{
  location: {
    type: "Point",
    coordinates: [116.4074, 39.9042]
  }
}

// LineString
{
  route: {
    type: "LineString",
    coordinates: [
      [116.0, 39.0],
      [117.0, 40.0]
    ]
  }
}

// Polygon
{
  area: {
    type: "Polygon",
    coordinates: [[
      [116.0, 39.0],
      [117.0, 39.0],
      [117.0, 40.0],
      [116.0, 40.0],
      [116.0, 39.0]
    ]]
  }
}

五、文本搜索 #

5.1 创建文本索引 #

javascript
// 创建文本索引
db.articles.createIndex({ title: "text", content: "text" })

// 创建多语言文本索引
db.articles.createIndex(
  { content: "text" },
  { default_language: "chinese" }
)

// 指定权重
db.articles.createIndex(
  { title: "text", content: "text" },
  { weights: { title: 10, content: 5 } }
)

5.2 文本搜索 #

javascript
// 基本文本搜索
db.articles.find({ $text: { $search: "数据库" } })

// 多词搜索(OR关系)
db.articles.find({ $text: { $search: "数据库 MongoDB" } })

// 短语搜索
db.articles.find({ $text: { $search: "\"文档数据库\"" } })

// 排除词
db.articles.find({ $text: { $search: "数据库 -MySQL" } })

5.3 文本搜索评分 #

javascript
// 获取搜索相关性评分
db.articles.find(
  { $text: { $search: "数据库" } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

六、$lookup关联查询 #

6.1 基本关联 #

javascript
// 左连接
db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  }
])

// 输出
{
  "_id": ObjectId("..."),
  "orderNo": "ORD001",
  "userId": ObjectId("..."),
  "user": [
    {
      "_id": ObjectId("..."),
      "name": "张三",
      "email": "zhangsan@example.com"
    }
  ]
}

6.2 多条件关联 #

javascript
// 复杂关联条件
db.orders.aggregate([
  {
    $lookup: {
      from: "products",
      let: { productId: "$productId", qty: "$quantity" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: ["$_id", "$$productId"] },
                { $gte: ["$stock", "$$qty"] }
              ]
            }
          }
        }
      ],
      as: "availableProducts"
    }
  }
])

6.3 关联后处理 #

javascript
// 展开数组并选择字段
db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  },
  {
    $unwind: "$user"
  },
  {
    $project: {
      orderNo: 1,
      amount: 1,
      userName: "$user.name",
      userEmail: "$user.email"
    }
  }
])

七、$graphLookup图查询 #

7.1 递归关联 #

javascript
// 组织架构递归查询
db.employees.aggregate([
  {
    $graphLookup: {
      from: "employees",
      startWith: "$managerId",
      connectFromField: "managerId",
      connectToField: "_id",
      as: "managers",
      depthField: "level"
    }
  }
])

7.2 限制深度 #

javascript
// 限制递归深度
db.categories.aggregate([
  {
    $graphLookup: {
      from: "categories",
      startWith: "$parentId",
      connectFromField: "parentId",
      connectToField: "_id",
      maxDepth: 3,
      as: "ancestors"
    }
  }
])

八、查询优化技巧 #

8.1 索引覆盖查询 #

javascript
// 创建复合索引
db.users.createIndex({ email: 1, name: 1 })

// 索引覆盖查询(只返回索引字段)
db.users.find(
  { email: "test@example.com" },
  { _id: 0, email: 1, name: 1 }
)

8.2 查询提示 #

javascript
// 强制使用指定索引
db.users.find({ email: "test@example.com" }).hint({ email: 1 })

// 禁用索引
db.users.find({ email: "test@example.com" }).hint({ $natural: 1 })

8.3 批量大小优化 #

javascript
// 设置批量大小
db.users.find({}).batchSize(100)

// 流式处理大数据
const cursor = db.users.find({}).batchSize(100);
while (cursor.hasNext()) {
  const doc = cursor.next();
  // 处理文档
}

8.4 查询超时设置 #

javascript
// 设置最大执行时间
db.users.find({}).maxTimeMS(5000)

// 聚合查询超时
db.users.aggregate([...], { maxTimeMS: 10000 })

九、实际应用示例 #

9.1 多条件搜索 #

javascript
function advancedSearch(options) {
  const pipeline = [];
  const match = {};
  
  // 关键词搜索
  if (options.keyword) {
    match.$text = { $search: options.keyword };
  }
  
  // 分类筛选
  if (options.category) {
    match.category = options.category;
  }
  
  // 价格范围
  if (options.minPrice || options.maxPrice) {
    match.price = {};
    if (options.minPrice) match.price.$gte = options.minPrice;
    if (options.maxPrice) match.price.$lte = options.maxPrice;
  }
  
  // 标签筛选
  if (options.tags && options.tags.length > 0) {
    match.tags = { $all: options.tags };
  }
  
  // 评分筛选
  if (options.minRating) {
    match.rating = { $gte: options.minRating };
  }
  
  pipeline.push({ $match: match });
  
  // 排序
  if (options.sortBy) {
    const sort = {};
    sort[options.sortBy] = options.sortOrder === 'desc' ? -1 : 1;
    pipeline.push({ $sort: sort });
  }
  
  // 分页
  pipeline.push({ $skip: (options.page - 1) * options.pageSize });
  pipeline.push({ $limit: options.pageSize });
  
  return db.products.aggregate(pipeline);
}

9.2 统计分析查询 #

javascript
// 销售统计分析
db.orders.aggregate([
  {
    $match: {
      createdAt: {
        $gte: new Date("2024-01-01"),
        $lt: new Date("2024-02-01")
      }
    }
  },
  {
    $group: {
      _id: {
        year: { $year: "$createdAt" },
        month: { $month: "$createdAt" },
        day: { $dayOfMonth: "$createdAt" }
      },
      totalSales: { $sum: "$amount" },
      orderCount: { $sum: 1 },
      avgOrderValue: { $avg: "$amount" }
    }
  },
  {
    $sort: { "_id.year": 1, "_id.month": 1, "_id.day": 1 }
  }
])

十、总结 #

10.1 高级查询技术 #

技术 用途
$expr 字段间比较
$elemMatch 数组元素匹配
$regex 正则匹配
$near 地理位置查询
$text 文本搜索
$lookup 关联查询
$graphLookup 递归关联

10.2 最佳实践 #

text
高级查询最佳实践:
├── 合理使用索引
├── 避免全表扫描
├── 使用explain分析性能
├── 设置查询超时
├── 分页处理大数据
└── 监控慢查询

下一步,让我们学习聚合管道!

最后更新:2026-03-27