mongo DB(二)

MongoDB 存取的是BSON(二進制 JSON)格式來表示。

題目

找出朋友中有amy 且有john
的資料

請把所有人的hobbies都加入reading 和 watch movie

找出email是帶有yahoo的資料

請找出25歲以下 或興趣有painting的資料

請把amy的email改成Amy@google.com,並且新增一個欄位是update_time 內容為現在時間

請把bob john加入sex:M的資料和欄位update_time 為現在時間
Alice Amy 加入sex:F的資料和欄位update_time為現在時間
db.student.update({name:{

\(in:["Bob,"john]}},{\)set:{sex:"M",update_time: new Date()}},{ multi: true } //另一種方法

請將alice的歲數乘2

請讓所有資料的age欄位至少要20歲
請將性別為男生的資料篩選出來並排序且不顯示欄位_id

​​​​show dbs
​​​​use mongo_class
​​​​db.student.insert([
​​​​  {
​​​​    name: "John",
​​​​    age: 25,
​​​​    email: "john@yahoo.com",
​​​​    hobbies: ["reading", "hiking"],
​​​​    friends: ["Alice", "Bob", "Amy"]
​​​​  },
​​​​  {
​​​​    name: "Alice",
​​​​    age: 30,
​​​​    email: "alice@example.com",
​​​​    hobbies: ["painting", "gardening"],
​​​​    friends: ["John", "Bob"]
​​​​  },
​​​​  {
​​​​    name: "Bob",
​​​​    age: 28,
​​​​    email: "bob@example.com",
​​​​    hobbies: ["cooking", "photography"],
​​​​    friends: ["John", "Alice", "Amy"]
​​​​  },
​​​​  {
​​​​    name: "Amy",
​​​​    age: 18,
​​​​    email: "AA@google.com",
​​​​    hobbies: ["cooking", "photography", "hiking"],
​​​​    friends: ["John", "Alice"]
​​​​  }
​​​​]
​​​​)
​​​​db.getCollection('student').find({ friends: { $all: ['Amy', 'John'] } }); // 查詢同時具有 'Amy' 和 'John' 作為朋友的學生資料

​​​​db.student.update({}, { $push: { "hobbies": { $each: ["reading", "watch movie"] } } }, { multi: true }); // 將 "reading" 和 "watch movie" 插入所有學生的 hobbies 陣列中

​​​​db.getCollection('student').find({ email: { $regex: "yahoo" } }); // 查詢 email 中包含 "yahoo" 的學生資料

​​​​db.getCollection('student').find({ $or: [{ age: { $lt: 25 } }, { hobbies: "painting" }] }); // 查詢年齡小於 25 或擁有 "painting" 興趣的學生資料

​​​​db.student.update({ name: "Amy" }, { $set: { email: "Amy@google.com", update_time: new Date() } }, { upsert: false }); // 更新名為 "Amy" 的學生的 email 和 update_time 欄位

​​​​db.student.update({ $or: [{ name: "Bob" }, { name: "John" }] }, { $set: { sex: "M", update_time: new Date() } }, { multi: true }); // 將名為 "Bob" 或 "John" 的學生的性別設置為 "M",並更新 update_time

​​​​db.student.update({ $or: [{ name: "Alice" }, { name: "Amy" }] }, { $set: { sex: "F", update_time: new Date() } }, { multi: true }); // 將名為 "Alice" 或 "Amy" 的學生的性別設置為 "F",並更新 update_time

​​​​db.student.update({ name: "Alice" }, { $mul: { age: 2 } },{ multi: true }); // 將名為 "Alice" 的學生的年齡乘以 2

​​​​db.student.update({}, { $max: { age: 20 } }, { multi: true }); // 將年齡小於 20 歲的學生的年齡設置為 20

​​​​db.student.update({ age: { $lt: 20 } }, { $set: { age: 20 } }, { multi: true });// 將年齡小於 20 歲的學生的年齡設置為 20 另一種方法

​​​​db.getCollection('student').find({ sex: "M" }, { _id: 0 }).sort({ age: 1 }); // 查詢性別為 "M" 的學生資料,並按照年齡升序排列,不顯示 _id 欄位

查詢總比數
db.people.count()

db.people.count({city:台北})

db.people.count({city:台北,sex:男})

Aggregate

db.collection.aggregate()

​​​​show dbs           // 顯示所有的數據庫
​​​​use mongo_class    // 切換到 mongo_class 數據庫
​​​​db.agg.insert({"id" : 1 ,"name" : "mark","age" : 20, "assets" :100000000 })    // 向 agg 集合插入一個文檔
​​​​db.agg.insert({"id" : 2, "name" : "steven", "age" : 40, "assets" :1000000 })    // 向 agg 集合插入一個文檔

​​​​// 使用聚合操作進行文檔轉換和選擇特定字段
​​​​db.agg.aggregate([{"$project":{"id":1,"name":1}}])    // 將 id 和 name 字段保留,其他字段過濾掉

​​​​// 使用聚合操作進行文檔篩選和過濾
​​​​db.agg.aggregate([{"$match":{age:{$gt:10,$lte:30}}}])    // 選擇 age 字段大於 10 且小於等於 30 的文檔

aggregate $sum $max運算值

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

db.students.update({ name: "Alice" },{ $max: { age: 25 } })
上述示例將更新 students 集合中 name 為 "Alice" 的文檔的 age 字段值,如果 age 字段的當前值小於 25,則更新為 25。

db.students.aggregate([
{
$group:{_id: null,maxAge: {

max:"age" }}},
{$project: {_id: 0,maxAge: 1} }
]).forEach(function(result) {db.students.update(
{ name: "Alice" },
{ $max: { age: result.maxAge } });});
首先使用 $group 階段計算了集合中所有文檔的 age 字段的最大值,並將結果保存在 maxAge 字段中。然後使用 $project 階段排除了 _id 字段,只保留了 maxAge 字段。最後,使用 forEach 循環遍歷結果,將 maxAge 的最大值應用到 name 為 "Alice" 的文檔的 age 字段上,使用 $max

總之$group 是聚合管道中的操作符,用於按指定字段將文檔分組。通過 $group,您可以對分組後的文檔應用各種聚合操作,例如計算總和、平均值、計數等。
$max 是 $group 階段中使用的一個聚合運算符,用於在分組後的文檔中找到指定字段的最大值。 $max 運算符需要指定要找到最大值的字段

練習一

​​​​show dbs
​​​​use mongo_class
​​​​db.ox.insert({"id" :1 , "status" : "o" , "count" : 5})
​​​​db.ox.insert({"id" :2 , "status" : "o", "count" : 5})
​​​​db.ox.insert({"id" :3 , "status" : "o", "count" : 5})
​​​​db.ox.insert({"id" :4 , "status" : "x", "count" : 10})
​​​​db.ox.insert({"id" :5 , "status" : "x", "count" : 10})
​​​​db.ox.insert({"id" :6 , "status" : "x", "count" : 11})

​​​​db.ox.aggregate([{"$group":{"_id":"$status"}}])
​​​​db.ox.aggregate([{"$group":{"_id":"$status","total":{"$sum":"$count"}}}])
​​​​db.ox.aggregate([{"$group":{"_id":{"a":"$status","b":"$count"}}}])

1.$group 操作按照 status 欄位的值進行分組,將具有相同 status 值的文檔分為一組。_id 指定了分組的依據,這裡使用 status 作為分組依據。
2.使用 $group 階段,通過 _id 欄位將文檔分組為不同的狀態。然後使用 $sum 運算符計算每個狀態的 count 欄位的總和
3.使用 $group 階段,並使用 _id 欄位來創建一個組合鍵,其中包含 status 欄位的值作為 a,count 欄位的值作為 b。

練習二

​​​​show dbs
​​​​use mongo_class
​​​​db.agg2.insert({"name" : "mark",
​​​​"fans" : [
​​​​{"name" : "steven","age":20},
​​​​{"name" : "max","age":60},
​​​​{"name" : "stanly","age":30}
​​​​]})
​​​​db.agg2.aggregate([{"$unwind":"$fans"}])

使用 $unwind 階段展開 fans 陣列,將每個 fans 對象拆分為單獨的文檔。

練習三

​​​​show dbs
​​​​use mongo_class
​​​​db.agg3.insert({"name" : "mark", "age" : 18})
​​​​db.agg3.insert({"name" : "steven", "age" : 38})
​​​​db.agg3.insert({"name" : "max", "age" : 10})
​​​​db.agg3.insert({"name" : "stanlly", "age" : 28})

​​​​db.agg3.aggregate([{"$sort":{"age":1}}])
​​​​db.agg3.aggregate([{"$limit":2}])
​​​​db.agg3.aggregate([{"$skip":3}])
  1. db.agg3.aggregate([{"$sort":{"age":1}}]): 這個聚合操作使用 $sort 階段按照 age 字段進行升序排序。結果將按照年齡從小到大排序。
  2. db.agg3.aggregate([{"$limit":2}]): 這個聚合操作使用 $limit 階段限制結果集的數量為 2。它將只返回前兩個文檔作為結果。
  3. db.agg3.aggregate([{"$skip":3}]): 這個聚合操作使用 $skip 階段跳過前 3 個文檔。它將從第 4 個文檔開始返回結果。

練習四

​​​​show dbs
​​​​use mongo_class
​​​​db.agg4.insert({ "id" : 1,"name" : "mark","age" : 20,"sex" : "M", "fans": [{"name" : "steven"},{"name" : "max"}],"phone" : "xxxxx"})
​​​​db.agg4.insert({ "id" : 2,"name" : "steven", "age" : 40,"sex" :"M","fans" : [{"name" : "mark"},{"name" : "max"}],"phone" : "xxxxx"})
​​​​db.agg4.insert({ "id" : 3,"name" : "marry","age" : 30,"sex" : "S", "fans": [{"name" : "mark"},{"name" : "max"},{"name" : "jack"}], "phone" :"xxxxx"})
​​​​db.agg4.insert({ "id" : 4,"name" : "jack","age" : 21,"sex" : "M","fans" :[{"name" : "mark"}],"phone" : "xxxxx" })

​​​​db.agg4.aggregate([
​​​​  { $sort: { age: 1 } }, // 按年齡升序排序
​​​​  { $match: { age: { $gt: 19, $lte: 29 } } }, // 年齡在 20 到 29 歲之間的文檔
​​​​  { $skip: 1 } // 跳過第一個文檔
​​​​])
​​​​db.agg4.aggregate([{"$match":{"sex":"M"}},{"$project":{"name":1,"age":1}},{ $sort: { age: 1 } },  // 按年齡升序排序
​​​​ { $skip: 1 },  // 跳過第一個文檔
​​​​  { $limit: 1 }  // 返回一個文檔
​​​​])

mapReduce練習一

​​​​show dbs
​​​​use mongo_class
​​​​db.order.insertMany([{ "class" : "1", "price" : 10,"count" : 180},
​​​​{ "class" : "1" ,"price" : 10,"count" : 350},
​​​​{ "class" : "2" ,"price" : 10,"count" : 90},
​​​​{ "class" : "2" ,"price" : 10,"count" : 320},
​​​​{ "class" : "2" ,"price" : 10,"count" : 150}])

​​​​var result = db.order.mapReduce(
​​​​  // 映射函式
​​​​  function() {
​​​​    // 計算價格和數量的乘積
​​​​    var total = this.price * this.count;
​​​​    // 使用 "class" 作為鍵(key),將結果發射(emit)出來
​​​​    emit(this.class, total);
​​​​  },
​​​​  // 減少函式
​​​​  function(key, values) {
​​​​    var total = 0;
​​​​    // 將同一鍵的所有值進行加總
​​​​    for (var i = 0; i < values.length; i++) {
​​​​      total += values[i];
​​​​    }
​​​​    // 返回每個 "class" 的總和
​​​​    return total;
​​​​  },
​​​​  // 選項:指定結果存儲的集合名稱為 "mapReduceTest"
​​​​  { out: "mapReduceTest" }
​​​​);

​​​​// 檢索 "mapReduceTest" 集合中的所有文檔
​​​​db.mapReduceTest.find();

mapReduce練習二

​​​​show dbs
​​​​use mongo_class
​​​​db.order_2.insertMany([{"class" : "1", "price" : 10,"count" : 180},
​​​​{ "class" : "1" ,"price" : 10,"count" : 350},
​​​​{ "class" : "2" ,"price" : 10,"count" : 90},
​​​​{ "class" : "2" ,"price" : 10,"count" : 320},
​​​​{ "class" : "2" ,"price" : 10,"count" : 150},
​​​​{ "class" : "3" ,"price" : 10,"count" : 100},
​​​​{ "class" : "3" ,"price" : 10,"count" : 200},
​​​​{ "class" : "3" ,"price" : 10,"count" : 300}] )

​​​​var result = db.order_2.mapReduce(
​​​​  // 映射函式
​​​​  function() {
​​​​    // 計算價格和數量的乘積
​​​​    var total = this.price * this.count;
​​​​    // 使用 "class" 作為鍵(key),將結果發射(emit)出來
​​​​    emit(this.class, total);
​​​​  },
​​​​     // 減少函式
​​​​  function(key, values) {
​​​​    var total = 0;
​​​​    // 將同一鍵的所有值進行加總
​​​​    for (var i = 0; i < values.length; i++) {
​​​​      total += values[i];
​​​​    }
​​​​    // 返回每個 "class" 的總和
​​​​    return total;
​​​​  },
​​​​  // 選項:指定結果存儲的集合名稱為 "Test"
​​​​  {
​​​​    out: "Test",
​​​​    query: {
​​​​      class: { "$in": ["2", "3"] }
​​​​    },
​​​​    finalize: function(key, reducedVal) {
​​​​      // 在最終處理階段對值進行最後處理
​​​​      reducedVal = reducedVal + " dollar";
​​​​      return reducedVal;
​​​​    }
​​​​  }
​​​​);
​​​​// 檢索 "Test" 集合中的所有文檔
​​​​db.Test.find();

牛刀小試

查詢年齡大於等於30的個數
查詢台北市的人數
查詢年齡介於20到40之間且居住在台北市的人數
查詢每個區域(district)的平均年齡
查詢台北市每個區域的人數

​​​​show dbs
​​​​use mongo_class
​​​​db.order_3.insertMany([
​​​​  { city: "台北市", district: "北投", age: 25 },
​​​​  { city: "台北市", district: "士林", age: 20 },
​​​​  { city: "台北市", district: "士林", age: 30 },
​​​​  { city: "台北市", district: "大同", age: 30 },
​​​​  { city: "台北市", district: "大同", age: 40 },
​​​​  { city: "台北市", district: "大同", age: 50 },
​​​​  { city: "台北市", district: "中山", age: 15 },
​​​​  { city: "台北市", district: "中山", age: 25 },
​​​​  { city: "台北市", district: "松山", age: 18 },
​​​​  { city: "台北市", district: "松山", age: 22 },
​​​​  { city: "台北市", district: "松山", age: 35 },
​​​​  { city: "台北市", district: "松山", age: 45 },
​​​​  { city: "新北市", district: "板橋", age: 22 },
​​​​  { city: "新北市", district: "三重", age: 45 },
​​​​  { city: "新北市", district: "中和", age: 50 },
​​​​  { city: "新北市", district: "永和", age: 34 },
​​​​  { city: "新北市", district: "新莊", age: 45 },
​​​​  { city: "新北市", district: "新店", age: 14 },
​​​​  { city: "新北市", district: "土城", age: 47 },
​​​​  { city: "新北市", district: "蘆洲", age: 24 },
​​​​  { city: "新北市", district: "汐止", age: 35 },
​​​​  { city: "新北市", district: "樹林", age: 29 },
​​​​  { city: "新北市", district: "淡水", age: 43 },
​​​​  { city: "新北市", district: "鶯歌", age: 24 }
​​​​])

​​​​db.order_3.count({"age":{$lt:30}})
​​​​db.order_3.count({city:"台北市"})
​​​​db.order_3.count({$and:[{"age":{$gte:20,$lte:40}},{city:"台北市"}]})
​​​​db.order_3.count({"age":{$gte:20,$lte:40},city:"台北市"})//簡化版
​​​​db.order_3.aggregate([{"$group":{"_id":"$city","total":{"$avg":"$age"}}}])
​​​​db.order_3.aggregate([{"$match":{city: "台北市"}},{"$group":{"_id":"$district","total":{$sum:1}}}])

索引

優點:收尋速度快
在使用分組或排序時速度快
缺點:占空間
show dbs
use mongo_class
db.tests.insert({"x":"hello"})

​​​​db.tests.ensureIndex({"x":1})
​​​​db.tests.getIndexes()
​​​​
​​​​    // 在 test_1 集合中插入 100,000 個文件
​​​​for (var i=0;i<100000;i++){db.test_1.insert({"x":i})}
​​​​    // 建立 x 欄位的索引
​​​​    db.test_1.ensureIndex({"x":1})
​​​​    // 查詢 test_1 集合中 x 大於 500,000 的文檔並進行降序排序
​​​​    db.test_1.find({ "x": { "$gt": 500000 } }).sort({ "x": -1 }).explain("executionStats")

​​​​// 在 test_2 集合中插入 100,000 個文件
​​​​for (var i = 0; i < 100000; i++) {db.test_2.insert({ "x": i})}

​​​​// 查詢 test_2 集合中 x 大於 500,000 的文檔並進行降序排序
​​​​db.test_2.find({ "x": { "$gt": 500000 } }).sort({ "x": -1 }).explain("executionStats")