說在前面的話
本文所有的操作示例,都以集合“HistoryTaskBase”為例。
一、查詢
1、時間區間
查詢“通知時間”介于2019-09-01到2019-10-01之間的數據。
db.getCollection('HistoryTaskBase').find({notifyTime:{$gte:ISODate('2019-09-01T00:00:00.000Z'),$lte:ISODate('2019-10-01T00:00:00.000Z')}})
2、統計
db.getCollection('HistoryTaskBase').find({notifyTime:{$lte:ISODate('2023-11-10T00:00:00.000Z')}}).count()// 總記錄數
39465
3、分頁(skip和limit)
假設每頁查詢10條記錄,分頁查詢第二頁,語句見下:
- skip 跳過前面多少條記錄
- limit 限制查詢多少條記錄
db.getCollection('HistoryTaskBase').find({notifyTime:{$lte:ISODate('2023-11-10T00:00:00.000Z')}}).skip(10).limit(10)
4、排序sort
- 降序-1
db.getCollection('HistoryTaskBase').find({notifyTime:{$gte:ISODate('2019-09-01T00:00:00.000Z'),$lte:ISODate('2023-12-01T00:00:00.000Z')}}).sort({notifyTime:-1})
- 升序1
db.getCollection('HistoryTaskBase').find({notifyTime:{$gte:ISODate('2019-09-01T00:00:00.000Z'),$lte:ISODate('2023-12-01T00:00:00.000Z')}}).sort({notifyTime:-1})
- 多重排序
先按schoolId升序,再是createdOn倒序
db.getCollection('xxx').find({}).sort({schoolId: 1, createdOn:-1});
5、in集合
totalIds 是一個數組類型,在查詢包含關系的時候,使用In集合。
db.getCollection('xxx').find({"totalIds":{$in:[152290]}});
6、nin不存在集合
是in的相反操作,不存在于集合里。
7、比較操作
- $eq:等于
- $ne:不等于
- $lt:小于
- $lte:小于等于
- $gt:大于
- $gte:大于等于
db.getCollection('xxx').find({"classroomId":{$eq:"067JOE"}});db.getCollection('xxx').find({"classroomId":{$ne:"067JOE"}});
像前文說的時間區間查詢,就是使用大于小于的比較操作實現。因為都比較簡單,就不一一舉例了。
8、存在性操作
檢查字段是否存在
db.getCollection('xxx').find({"classroomId":{$exists: true}});
9、數組查詢
- size-查詢數組的長度等于1的記錄
db.getCollection('xxx').find({"totalIds":{$size: 1}});
- elemMatch-匹配數組中的元素
要查詢數組desktopList下的數組taskList的taskId=“2ASS229CMY”
數據結構示例:
{"_id":"5c6cfc303daedd4e40fe91f5","userId":150908,"classroomId":"ZN41B3","taskTotalNumber":5,"desktopList":[{"desktopId":"IQZ5SN2R","classId":0,"classMemNumber":0,"desktopType":0,"taskList":[{"taskId":"2ASS229CMY","taskType":1,"materialId":"ZQ9T1JCA2U"}]}]
}
mongodb查詢語句寫法見下:
db.getCollection('xxx').find({"desktopList": {"$elemMatch": {"taskList": {"$elemMatch": {"taskId": "2ASS229CMY"}}}}
});
10、邏輯查詢
- $and
默認,多個條件的查詢就是and了。
它的語法格式是:{ $and: [ { }, { }, … , { } ] }
示例:
查詢userId=152408且schoolId=684的記錄
db.getCollection('ClassroomBase').find({ $and: [ { "userId" : 152408 }, { "schoolId": 684 } ] } );// 等同于下面的語句
db.getCollection('ClassroomBase').find({ "userId" : 152408 , "schoolId": 684 } );
- $or
語法格式是:{ $or: [ { }, { }, … , { } ] }
示例見下:
查詢userId=152408或schoolId=684的記錄
db.getCollection('ClassroomBase').find({ $or: [ { "userId" : 152408 }, { "schoolId": 684 } ] } );
- $nor
語法格式是:{ $nor: [ { }, { }, … { } ] },它是or的取反。
繼續上面的示例,就變成了要查詢userId != 152408 且 schoolId != 684的記錄
db.getCollection('ClassroomBase').find({ $nor: [ { "userId" : 152408 }, { "schoolId": 684 } ] } );
- $not
需要注意的是,它會查詢出不包含該字段的文檔。
語法各是:{ field: { $not: { } } },邏輯運算中,簡單的取反。一般是針對單條件而言。
比如,查詢語句見下:
db.getCollection('xxx').find({ schoolId: { $not: { $gt: 1000 } } });
它將查詢出schoolId 不大于1000的記錄,也會把schoolId為空的記錄查詢出來。
二、刪除
1、deleteMany-批量刪除
推薦使用這個,匹配到多少就刪除多少條記錄。
db.getCollection('HistoryTaskBase').deleteMany({notifyTime:{$gte:ISODate('2019-09-01T00:00:00.000Z'),$lte:ISODate('2019-10-01T00:00:00.000Z')}})// 返回
{"acknowledged" : true,"deletedCount" : 3693.0
}
2、deleteOne-刪除單條記錄
db.getCollection('xxx').deleteOne({"_id":"5c6cfc303daedd4e40fe91f4", "isDelete": true});// 返回
{"acknowledged" : true,"deletedCount" : 0.0
}
3、findOneAndDelete-刪除并返回刪除前的文檔
與上一個操作語句不同,會返回刪除前的文檔。相同的是:都會刪除該記錄。
db.getCollection('xxx').findOneAndDelete({"classroomId":"ZN41B3"});
再次查詢,則返回0條記錄:
三、聚合操作
- $match: 過濾文檔,只保留滿足指定條件的文檔
- $group: 對文檔進行分組操作
示例一:聚合查詢最近幾天(2023-11-20到2023-11-23)創建的課堂,按天求和,算出每一天的總人數。
- createdOn 創建時間
- $dayOfYear 操作符從 createdOn 中提取出一年中的第幾天,并以此為基準進行分組
- $addToSet 操作符用于將符合條件的 totalIds 字段的值添加到一個集合中。
這意味著對于每個分組(每天的文檔),都會創建一個包含唯一 totalIds 值的集合。
db.getCollection('xxx').aggregate([{ $match : { createdOn:{$gte:ISODate('2023-11-20T00:00:00.000Z'),$lte:ISODate('2023-11-24T00:00:00.000Z')},isDelete:false } },{$group: {_id: { day: { $dayOfYear: "$createdOn" } },userIds : {$addToSet : "$totalIds"}}
}
])
返回值
示例二:聚合查詢最近幾天(2023-11-20到2023-11-23)創建的課堂數,按天分組。
db.getCollection('xxx').aggregate([{ $match : { createdOn:{$gte:ISODate('2023-11-20T00:00:00.000Z'),$lte:ISODate('2023-11-24T00:00:00.000Z')},isDelete:false } },{$group: {_id: { day: { $dayOfYear: "$createdOn" } },total: { $sum: 1 }}
}
])
// 聚合結果
其他聚合
除了$sum外,還有最大、最小和平均等常用的函數。
{$group: {_id: "$field",total: { $sum: 1 },average: { $avg: "$numericField" },max: { $max: "$numericField" },min: { $min: "$numericField" }}
}
$lookup
本示例是查詢訂單,然后外關聯商品表,主外鍵是productId。
db.orders.aggregate([{$lookup: {from: "products",localField: "productId",foreignField: "_id",as: "product"}},{$unwind: "$product" // 展開 product 數組}
]);
- orders數據示例
{"_id": 1,"orderNumber": "NO123","productId": 101,"quantity": 2
}
- products數據示例
{"_id": 101,"productName": "商品名稱","price": 1000
}
- 查詢結果見下,通過$unwind,將匹配到的商品文檔變為單獨的文檔。
{"_id": 1,"orderNumber": "NO123","productId": 101,"quantity": 2,"product": {"_id": 101,"productName": "商品名稱","price": 1000}
}
四、函數
在 MongoDB 的 shell 環境中,你可以使用 JavaScript 來編寫條件語句。這里只列舉幾個作為示例。
1、foreach
多個集合的嵌套循環查詢
- 先查詢ClassroomBase,得到其classroomId
- 再傳遞給Desktop,作為查詢條件進行查詢
- 遍歷結果,對數組taskList的長度進行累加
// 查詢各個課堂的人數和任務數
db.xxx.find({"isDelete": false}).forEach(function (doc) {// 任務數var taskSize = 0;// 嵌套查詢db.Desktop.find({"classroomId": doc.classroomId}, {"desktopList": 1}).forEach(function(doc){doc.desktopList.forEach(function(task) {taskSize += task.taskList.length})});print("老師ID:" + doc.userId + " 課堂ID:" + doc.classroomId + " 人數:" + doc.totalIds.length + " 任務數: " + taskSize)
2、print
輸出查詢結果
3、push
查詢2022-12-25這一天上課的課堂ID列表
var classroomIds = new Array();
db.xxx.find({startTime:{$gte:ISODate('2022-12-25T00:00:00.000Z'),$lte:ISODate('2022-12-26T00:00:00.000Z')},isDelete:false}).forEach(function (doc) {classroomIds.push(doc.classroomId);})// 輸出課堂ID數組
print(classroomIds.length);
4、if
var x = 10;if (x > 5) {print("x 大于 5");
} else if (x === 5) {print("x 等于 5");
} else {print("x 小于 5");
}
5、switch
var day = "Monday";switch (day) {case "Monday":print("星期一");break;case "Tuesday":print("星期二");break;// 其他 case 語句default:print("其他天");
}
6、三目運算
var age = 20;
var message = (age >= 18) ? "成年人" : "未成年人";
print(message);
五、總結
mongodb還有一些運維,比如定期備份、集群管理等,有空再整理。
mongodb的修改操作,也未在本文涉及。
本文側重于mongodb的查詢,說實話,查詢才是最復雜的。
希望可以幫助到你,有空我再更新~~