Mongodb 的高級查詢

關鍵詞:mongodb, mongo, project, group, aggregate, 聚合管道, 高級查詢

簡介

管道,即,前一個操作的輸出(結果)是后一個操作的輸入。

雞蛋 -> 分出雞蛋清 -> 加入牛奶并打發 -> 奶油

這就是一個管道,有四個階段,前一個階段的結果是后一個的輸入。
管道,可能是因為看起來像一個管道

mongo 的管道操作

db.collection.aggregate( [ { <stage> }, ... ] )

例如,對user文檔進行管道聚合:

db.user.aggregate([
  {第一個操作},
  {第二個操作},
  {第三個操作}
])

其中每個操作可以對應下面的任意一個:

例如有user的庫(collection)

{
  username: 'abc',
  password: '123'
}

1. $project「投影」

db.user.aggregate([
  {
    $project: {
      username: 1
    }
  }
])

或者看起來是這樣(為了和上面對比):

db.user.aggregate([
  { $project: {username: 1} }
])

查詢結果:

{
  username: 'abc'
}

1 == true 保留
0 == false 丟棄
下面同理

2. $match「匹配」

匹配出滿足條件的數據項,條件與mongo查詢條件一致

db.user.aggregate([
  { $match: { username: 'abc' } }
])

注意:如果需要按條件聚合的話,優先使用$match操作,會提高效率

例如應該這樣:

db.user.aggregate([
  { $match: { username: 'abc' } }, // 放在首位
  { $project: { username: 1 } }
])

不是這樣:

db.user.aggregate([
  { $project: { username: 1 } },
  { $match: { username: 'abc' } }
])

3. $group「分組」

對數據進行分組,我一般用于統計使用,暫時沒有用作其他

db.user.aggregate([
  { $group: {_id: '$username', sum: { $sum: 1 } } }
])

格式化一下:

db.user.aggregate([
  {
    $group: {
      _id: '$username', // _id 是 group 操作的必須參數,即要分組的主鍵
      sum_result: { $sum: 1 } // sum_result 是自定義結果字段,$sum 是操作符,這里意思是「加 1」
    }
  }
])

稍微解釋一下:
_id 是必須的字段:

  • 后面接 1 ,意思就是有多少條數據就返回多少條結果;
  • 后面接字段名(即:"$ + 字段名" 形式),會以該字段進行分組,所有此字段的值相同的數據都將分到同一組

sum_result 是自定義字段:

  • 結果(value)為 { $sum: 1 },即加1,也可以寫成 { $sum: '$username' } 類似的字段名,如果該字段為數字,則累加數字;
  • 分到同一組的每條都將執行一次本操作,本示例得到的結果為,同名的用戶個數統計

具體使用示例參考如下

請替換 collectionName 為自己所要操作的文檔(庫)名

db.collectionName.aggregate([
  {
    $match: { // 匹配 date 字段在 start_time 和 end_time 之間的數據
      date: { $gt: start_time, $lt: end_time }
    }
  }, {
    $project: { // 投影
      user: 1,
      type_1: { // 如果 type 字段等于 1,則 type_1 等于 1,否則為 null
        $cond: [ { $eq: ['$type', 1 ] }, 1, null ]
      },
      type_2: { // 如果 type 字段等于 2,則 type_2 等于 1,否則為 null
        $cond: [ { $eq: ['$type', 2 ] }, 1, null ]
      }
    }
  }, {
    $group: {  // 分組
      _id: '$user',
      chat: {$sum: '$type_1'}, // 累加 type_1 字段
      check: {$sum: '$type_2'} // 累加 type_2 字段
    }
  }
]);

舉個栗子

去重復后的數量

db.collectionName.aggregate([
  {
    $match: {
      isAdded: false // 一些篩選條件
    }
  }, {
    $group: {  // 分組
      _id: '$content', // 需要去重的字段
    }
  }, {
    $group: {  // 分組
      _id: 1,
      count: {$sum: 1} // 去重之后的數量
    }
  }
]);

操作數組中的數據(相乘)

db.yourCollection.aggregate([
  {
    $match: {
      type: "something your condition",
      created_at: { $gte: new Date("2020-03-03T10:40:00"), $lt: new Date("2020-03-03T20:40:59") },
    },
  },
  {
    $project: {
      draw_count: 1,
      total_value: {
        $reduce: {
          input: "$items",
          initialValue: 0,
          in: { $add: ["$$value", { $multiply: ["$$this.item.value", "$$this.item.count"] }] },
        },
      },
    },
  },
  {
    $group: {
      _id: "$draw_count",
      count: { $sum: 1 },
      value: { $sum: "$total_value" },
    },
  },
]);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容