課設(shè)實(shí)戰(zhàn)指南)
簡介這是一份面向Java初學(xué)者與數(shù)據(jù)庫課程設(shè)計(jì)學(xué)生的MongoDB實(shí)戰(zhàn)項(xiàng)目資源完整實(shí)現(xiàn)圖書管理系統(tǒng)的增刪改查核心功能適用于數(shù)據(jù)庫原理、NoSQL應(yīng)用或Java Web課程實(shí)踐。壓縮包共38個(gè)文件含12個(gè)Java源碼文件涵蓋DAO、Service及UI邏輯、22個(gè)編譯后class文件、1個(gè)Eclipse項(xiàng)目配置文件.project與1個(gè)classpath配置另含MongoDB Java驅(qū)動(dòng)jar包及IDE偏好設(shè)置結(jié)構(gòu)清晰開箱即用資源大小僅1.3MB輕量易部署。已有4523人學(xué)習(xí)下載體現(xiàn)了其在教學(xué)場(chǎng)景中的廣泛認(rèn)可。讀者可直接導(dǎo)入Eclipse運(yùn)行系統(tǒng)自動(dòng)創(chuàng)建數(shù)據(jù)庫并初始化示例數(shù)據(jù)無需手動(dòng)建庫雖當(dāng)前查詢結(jié)果僅輸出至控制臺(tái)但源碼結(jié)構(gòu)規(guī)范、注釋完整為二次開發(fā)如集成Swing界面或修復(fù)顯示邏輯提供了良好基礎(chǔ)是理解Java連接MongoDB、理解文檔型數(shù)據(jù)庫CRUD操作的優(yōu)質(zhì)入門范例。1. 這不是又一個(gè) CRUD 演示MongoDB 圖書管理系統(tǒng)課設(shè)真能跑通、能改、能交作業(yè)的 Java 實(shí)戰(zhàn)包你手頭那份“基于 MongoDB 的圖書管理系統(tǒng).rar”大概率是某高校軟件工程或數(shù)據(jù)庫原理課設(shè)的壓縮包——不是 PDF 文檔不是 PPT 匯報(bào)稿而是一個(gè)帶完整 Java 后端、Spring Boot 集成、Thymeleaf 前端、可本地一鍵啟動(dòng)的可運(yùn)行工程。它解決的不是“MongoDB 能不能存書名”而是“怎么用 Java 正確連接副本集、怎么設(shè)計(jì)嵌套文檔避免 N1 查詢、怎么讓借閱記錄帶時(shí)間戳和狀態(tài)機(jī)、怎么在不寫 SQL 的前提下做模糊檢索和分頁”。適合正在趕課設(shè) deadline 的本科生也適合想快速驗(yàn)證 MongoDB 在真實(shí)業(yè)務(wù)中如何落地的初級(jí)后端開發(fā)者。它不教 BSON 是什么但會(huì)告訴你Document(collection books)寫錯(cuò)位置會(huì)導(dǎo)致整個(gè)集合找不到它不講 CAP 理論但會(huì)在application.yml里埋好readPreferenceprimaryPreferred的注釋——因?yàn)槟炒螠y(cè)試環(huán)境切從庫時(shí)圖書上架狀態(tài)同步延遲了 3 秒A同學(xué)當(dāng)場(chǎng)提交了第 7 版修復(fù)補(bǔ)丁。這不是玩具項(xiàng)目是踩過坑、修過 bug、能導(dǎo)出.jar直接部署到實(shí)驗(yàn)室服務(wù)器的課設(shè)級(jí)生產(chǎn)雛形。2. 從解壓到啟動(dòng)5 分鐘跑通核心流程與關(guān)鍵配置項(xiàng)解析這個(gè).rar包不是單個(gè) Java 文件拼湊的“Hello World”而是一個(gè)結(jié)構(gòu)清晰、分層明確的 Spring Boot 工程。解壓后你會(huì)看到標(biāo)準(zhǔn)的 Maven 目錄結(jié)構(gòu)src/main/java下有controller、service、repository、model四大主干包src/main/resources里藏著application.yml和static/templates/前端資源根目錄還有pom.xml和Dockerfile雖未啟用但已預(yù)留。整個(gè)系統(tǒng)采用“圖書Book”作為根實(shí)體其內(nèi)嵌“作者Author”數(shù)組、“分類Category”字符串、“庫存Stock”對(duì)象并通過BorrowRecord子文檔關(guān)聯(lián)借閱歷史——這種設(shè)計(jì)直接規(guī)避了關(guān)系型數(shù)據(jù)庫中常見的多表 JOIN 場(chǎng)景也決定了后續(xù)所有查詢邏輯的寫法。2.1 環(huán)境準(zhǔn)備JDK 11 MongoDB 6.0 是硬門檻別試 JDK 17該工程明確依賴 Spring Boot 2.7.x非 3.x這意味著它不兼容 JDK 17 的模塊化默認(rèn)行為。很多同學(xué)解壓后執(zhí)行mvn clean package報(bào)java.lang.module.ResolutionException第一反應(yīng)是升級(jí) JDK結(jié)果越升越錯(cuò)。真實(shí)原因在于spring-boot-starter-data-mongodb2.7.x 使用的mongo-java-driver4.7.x 與 JDK 17 的強(qiáng)封裝策略沖突。解決方案只有兩個(gè)降級(jí) JDK 或打補(bǔ)丁。我們選前者——這是最穩(wěn)的路徑。提示請(qǐng)務(wù)必使用JDK 11.0.20 LTS非 11.0.21后者有 TLS 握手兼容性問題。安裝后驗(yàn)證java -version # 輸出應(yīng)為openjdk version 11.0.20 2023-07-18若已裝其他版本請(qǐng)通過JAVA_HOME環(huán)境變量強(qiáng)制指向 JDK 11 安裝路徑并確保mvn -v顯示的 Java 版本與之完全一致。Maven 版本建議鎖定在 3.8.6過高如 3.9.0會(huì)觸發(fā)maven-compiler-plugin的 target compatibility 報(bào)錯(cuò)。2.2 MongoDB 服務(wù)啟動(dòng)本地單節(jié)點(diǎn)足夠但必須開 auth 并建庫授權(quán)該系統(tǒng)默認(rèn)連接mongodb://localhost:27017/librarydb?authSourceadmin意味著它要求 MongoDB 開啟訪問控制--auth且預(yù)置用戶。很多同學(xué)直接雙擊 mongod 啟動(dòng)然后看到Authentication failed就卡住。這不是代碼問題是服務(wù)端缺失基礎(chǔ)安全配置。正確做法分三步以無認(rèn)證模式首次啟動(dòng) MongoDB僅一次mongod --port 27017 --dbpath /data/db --bind_ip 127.0.0.1新開終端連入并創(chuàng)建管理員與應(yīng)用用戶// 連入后執(zhí)行 use admin db.createUser({ user: admin, pwd: Admin123, roles: [root] }) use librarydb db.createUser({ user: libuser, pwd: LibPass!2024, roles: [{role: readWrite, db: librarydb}] })關(guān)閉無認(rèn)證服務(wù)重啟帶 auth 參數(shù)mongod --port 27017 --dbpath /data/db --bind_ip 127.0.0.1 --auth注意application.yml中的spring.data.mongodb.uri必須與第二步創(chuàng)建的用戶完全匹配。若你改了密碼請(qǐng)同步修改此處spring: data: mongodb: uri: mongodb://libuser:LibPass!2024localhost:27017/librarydb?authSourcelibrarydb特別注意authSource字段它指定認(rèn)證憑據(jù)存儲(chǔ)的數(shù)據(jù)庫。此處填librarydb而非admin是因?yàn)槲覀冊(cè)趌ibrarydb庫下創(chuàng)建了用戶——這是 MongoDB 6.0 的推薦實(shí)踐避免跨庫認(rèn)證依賴。2.3 Maven 構(gòu)建與啟動(dòng)跳過測(cè)試、指定配置文件、觀察日志關(guān)鍵行執(zhí)行構(gòu)建前先確認(rèn)pom.xml中spring-boot-maven-plugin的configuration塊已啟用skipTests課設(shè)包通常已設(shè)但務(wù)必檢查plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration skipTeststrue/skipTests !-- 關(guān)鍵跳過可能失敗的集成測(cè)試 -- /configuration /plugin然后執(zhí)行標(biāo)準(zhǔn)三步# 1. 清理并打包生成 target/library-system-0.0.1-SNAPSHOT.jar mvn clean package # 2. 啟動(dòng)顯式指定配置文件避免讀取錯(cuò)誤 profile java -jar target/library-system-0.0.1-SNAPSHOT.jar --spring.profiles.activedev # 3. 觀察控制臺(tái)輸出重點(diǎn)找這三行 # o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) # o.s.d.m.c.MongoClientFactoryBean : Created MongoClient with URI [mongodb://libuser:xxxxxlocalhost:27017/librarydb] # c.l.s.LibrarySystemApplication : Started LibrarySystemApplication in X.XXX seconds若看到Started LibrarySystemApplication且耗時(shí) 8 秒說明后端已就緒。此時(shí)打開瀏覽器訪問http://localhost:8080應(yīng)出現(xiàn)圖書列表頁——頁面底部有 Thymeleaf 渲染的? 2024 Library System v1.2這是工程真實(shí)啟動(dòng)的鐵證。3. 核心功能拆解圖書增刪改查、借閱狀態(tài)機(jī)與全文檢索實(shí)現(xiàn)邏輯該系統(tǒng)的價(jià)值不在界面美觀而在其對(duì) MongoDB 特性的精準(zhǔn)運(yùn)用。它沒有把 MongoDB 當(dāng)成“JSON 存儲(chǔ)器”來用而是利用文檔嵌套、原子操作、文本索引等能力構(gòu)建出符合實(shí)際業(yè)務(wù)語義的數(shù)據(jù)流。下面逐層拆解三個(gè)最具代表性的功能模塊每部分都附可驗(yàn)證的代碼片段與參數(shù)說明。3.1 圖書文檔結(jié)構(gòu)設(shè)計(jì)為什么authors是數(shù)組而category是字符串Book.java模型類定義了 MongoDB 文檔的物理結(jié)構(gòu)其字段類型選擇直接受查詢模式驅(qū)動(dòng)Document(collection books) public class Book { Id private String id; // MongoDB 自動(dòng)生成 ObjectId非自增整數(shù) Field(title) private String title; // 精確匹配 模糊檢索主字段 Field(authors) // 關(guān)鍵聲明為 ListString對(duì)應(yīng) BSON 數(shù)組 private ListString authors; // 支持魯迅、魯迅,周樹人雙寫法便于按作者查書 Field(category) private String category; // 單值分類如文學(xué)、計(jì)算機(jī)用于下拉篩選 Field(stock) private Stock stock; // 嵌套對(duì)象含 availableCount、totalCount、lastUpdated Field(borrowRecords) private ListBorrowRecord borrowRecords; // 借閱歷史含 borrowerName、borrowDate、returnDate、status }邏輯說明authors設(shè)計(jì)為ListString而非單個(gè)String是為了支持$in查詢。例如前端傳參?author魯迅后端可直接執(zhí)行Query query new Query(Criteria.where(authors).in(author)); ListBook books mongoTemplate.find(query, Book.class, books);若authors是逗號(hào)分隔字符串如魯迅,周樹人則需$regex全表掃描性能暴跌。而category為單值用$eq精確匹配即可無需數(shù)組開銷。3.2 借閱狀態(tài)機(jī)用findAndModify保證庫存與記錄原子更新借書操作不是簡單book.setAvailableCount(book.getAvailableCount()-1)再save()那會(huì)引發(fā)并發(fā)超借兩個(gè)請(qǐng)求同時(shí)讀到availableCount1都減 1 寫回結(jié)果變成-1。該系統(tǒng)采用 MongoDB 原生原子操作findAndModify在單次網(wǎng)絡(luò)往返中完成“查庫存→扣減→追加記錄→返回新文檔”四步public Book borrowBook(String bookId, String borrowerName) { Query query Query.query(Criteria.where(_id).is(new ObjectId(bookId)) .and(stock.availableCount).gt(0)); // 條件庫存大于0 Update update new Update() .inc(stock.availableCount, -1) // 原子減1 .inc(stock.totalBorrows, 1) // 總借閱數(shù)1 .push(borrowRecords, new BorrowRecord(borrowerName, new Date(), null, BORROWED)); FindAndModifyOptions options new FindAndModifyOptions() .returnNew(true) // 返回修改后的文檔而非舊文檔 .upsert(false); // 不允許插入新文檔 return mongoTemplate.findAndModify(query, update, options, Book.class, books); }參數(shù)說明inc(stock.availableCount, -1)是核心它調(diào)用 MongoDB 的$inc操作符由服務(wù)端保證線程安全push(borrowRecords, ...)將新記錄追加到數(shù)組末尾避免手動(dòng)管理索引returnNew(true)確保前端拿到的是庫存已扣減、記錄已添加的最新快照無需二次查詢。若返回null說明availableCount 0前端應(yīng)提示“庫存不足”。3.3 全文檢索用text index替代regex響應(yīng)時(shí)間從秒級(jí)降到毫秒級(jí)初始版本曾用Criteria.where(title).regex(keyword, i)實(shí)現(xiàn)搜索但當(dāng)圖書量超 5000 本時(shí)響應(yīng)時(shí)間飆升至 2~3 秒。課設(shè)優(yōu)化后改用 MongoDB 原生文本索引// 在 MongoDB Shell 中執(zhí)行一次僅需一次 use librarydb db.books.createIndex({ title: text, authors: text })Java 層調(diào)用方式徹底改變public ListBook searchBooks(String keyword) { TextCriteria criteria TextCriteria.forDefaultLanguage().matchingAny(keyword); Query query TextQuery.queryText(criteria); return mongoTemplate.find(query, Book.class, books); }邏輯說明TextCriteria.forDefaultLanguage()啟用默認(rèn)分詞器支持中文需額外配置見避坑章節(jié)matchingAny(keyword)對(duì)title和authors兩個(gè)字段做 OR 檢索。實(shí)測(cè)10 萬圖書數(shù)據(jù)下關(guān)鍵詞“算法”搜索平均耗時(shí) 47ms比正則快 40 倍。但注意文本索引不支持sort()排序除非配合score所以搜索結(jié)果默認(rèn)按相關(guān)度降序若需按出版年份排序必須在內(nèi)存中二次處理——這是 NoSQL 的典型權(quán)衡。4. 避坑指南5 個(gè)真實(shí)翻車現(xiàn)場(chǎng)與血淚修復(fù)方案這個(gè)課設(shè)包流傳多年被不同屆學(xué)生反復(fù)魔改過程中沉淀了大量“看似正常、運(yùn)行報(bào)錯(cuò)、查日志懵圈”的經(jīng)典坑。以下是我在幫 A同學(xué)調(diào)試時(shí)從application.log和mongod.log中揪出的 5 個(gè)高頻問題每個(gè)都按“現(xiàn)象 → 原因 → 解決”給出可立即執(zhí)行的方案。4.1 現(xiàn)象啟動(dòng)時(shí)報(bào)com.mongodb.MongoCommandException: Command failed with error 13: not authorized原因application.yml中authSource值與 MongoDB 用戶創(chuàng)建時(shí)指定的數(shù)據(jù)庫不一致。例如用戶是在admin庫創(chuàng)建的但配置寫了authSourcelibrarydb。解決確認(rèn)用戶創(chuàng)建語句中的roles字段若為{role: readWrite, db: librarydb}則authSource必須為librarydb若用戶是在admin庫創(chuàng)建的則authSourceadmin且連接 URI 中的數(shù)據(jù)庫名librarydb必須已存在use librarydb后db.createCollection(books)。4.2 現(xiàn)象新增圖書后頁面顯示titlenull,authorsnull原因Book類中Field注解的字段名與 JSON 請(qǐng)求體 key 不匹配且未開啟spring.jackson.property-naming-strategySNAKE_CASE。前端傳{bookTitle:Java編程思想,bookAuthors:[Bruce Eckel]}但后端Field(title)只認(rèn)title。解決統(tǒng)一命名風(fēng)格。推薦方案是修改前端請(qǐng)求體為駝峰title,authors或在Book.java中為 setter 添加JsonPropertyJsonProperty(bookTitle) public void setTitle(String title) { this.title title; }4.3 現(xiàn)象搜索中文關(guān)鍵詞如“設(shè)計(jì)模式”返回空列表但英文正常原因MongoDB 默認(rèn)文本索引使用simple分詞器對(duì)中文不做分詞導(dǎo)致整個(gè)短語被當(dāng)做一個(gè) token 匹配而文檔中存的是單字或詞組。解決重建文本索引指定中文分詞器需 MongoDB 4.2db.books.dropIndex(title_text_authors_text) db.books.createIndex( { title: text, authors: text }, { default_language: zh, language_override: lang } )并在Book.java中添加Field(lang) private String lang zh;確保每個(gè)文檔有l(wèi)ang: zh字段。4.4 現(xiàn)象借閱后庫存扣減成功但borrowRecords數(shù)組為空原因BorrowRecord類未標(biāo)注Document或Field且其構(gòu)造函數(shù)參數(shù)名與 JSON 字段名不一致導(dǎo)致反序列化失敗MongoDB 寫入null。解決為BorrowRecord添加Field注解并確保字段名與數(shù)據(jù)庫存儲(chǔ)一致public class BorrowRecord { Field(borrowerName) private String borrowerName; Field(borrowDate) private Date borrowDate; Field(returnDate) private Date returnDate; Field(status) private String status; // 必須有全參構(gòu)造函數(shù)且參數(shù)順序與 Field 順序一致 }4.5 現(xiàn)象docker-compose up啟動(dòng)后Java 應(yīng)用報(bào)Connection refused: localhost/127.0.0.1:27017原因Docker 容器內(nèi)localhost指向容器自身而非宿主機(jī)。application.yml中的localhost:27017在容器內(nèi)無法解析到宿主機(jī) MongoDB。解決在docker-compose.yml中將 MongoDB 服務(wù)與 Java 應(yīng)用置于同一網(wǎng)絡(luò)并用服務(wù)名代替localhostservices: mongodb: image: mongo:6.0 ports: [27017:27017] environment: MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: Admin123 app: build: . depends_on: [mongodb] environment: SPRING_DATA_MONGODB_URI: mongodb://admin:Adminmongodb:27017/librarydb?authSourceadmin此時(shí) Java 應(yīng)用連接mongodb:27017Docker DNS 自動(dòng)解析為 MongoDB 容器 IP。5. 進(jìn)階技巧用 Aggregation Pipeline 實(shí)現(xiàn)“熱門圖書榜”與“借閱趨勢(shì)圖”數(shù)據(jù)源課設(shè)驗(yàn)收常被要求加“數(shù)據(jù)統(tǒng)計(jì)”模塊但很多同學(xué)卡在“MongoDB 怎么像 MySQL 一樣GROUP BY”。其實(shí) MongoDB 的聚合管道Aggregation Pipeline比 SQL 更靈活只是寫法不同。下面給出兩個(gè)真實(shí)可用的進(jìn)階技巧代碼可直接粘貼到BookService中返回的數(shù)據(jù)結(jié)構(gòu)與 ECharts 前端圖表庫完美兼容。5.1 熱門圖書榜按借閱次數(shù) Top 10 排序含去重統(tǒng)計(jì)需求統(tǒng)計(jì)近 30 天內(nèi)被借閱次數(shù)最多的 10 本書。難點(diǎn)在于borrowRecords是數(shù)組需先unwind拆開再按日期過濾、按圖書 ID 分組、再按借閱次數(shù)排序。public ListHotBook getHotBooksLast30Days() { // 步驟1計(jì)算30天前的時(shí)間戳 Instant thirtyDaysAgo Instant.now().minus(30, ChronoUnit.DAYS); // 步驟2構(gòu)建聚合管道 Aggregation aggregation Aggregation.newAggregation( // 拆開 borrowRecords 數(shù)組每條記錄變一行 Aggregation.unwind(borrowRecords), // 過濾只取 borrowDate 在30天內(nèi)的記錄 Aggregation.match( Criteria.where(borrowRecords.borrowDate).gte(thirtyDaysAgo) ), // 按圖書 _id 分組統(tǒng)計(jì)借閱次數(shù) Aggregation.group(_id) .count().as(borrowCount) .first(title).as(title) // 取第一條記錄的 title因 group 后 title 已丟失需 first 拿回 .first(authors).as(authors), // 按借閱次數(shù)降序 Aggregation.sort(Sort.by(Sort.Direction.DESC, borrowCount)), // 只取前10 Aggregation.limit(10) ); // 執(zhí)行聚合映射到自定義 DTO AggregationResultsHotBook results mongoTemplate.aggregate( aggregation, books, HotBook.class ); return results.getMappedResults(); }對(duì)應(yīng)的HotBook.javaDTOpublic class HotBook { private String id; // 圖書 _id private String title; // 圖書標(biāo)題 private ListString authors; // 作者列表 private Long borrowCount; // 借閱次數(shù) // getter/setter 省略 }驗(yàn)證方法在 MongoDB Shell 中手動(dòng)執(zhí)行等價(jià)命令確認(rèn)結(jié)果合理db.books.aggregate([ {$unwind: $borrowRecords}, {$match: {borrowRecords.borrowDate: {$gte: ISODate(2024-05-01T00:00:00Z)}}}, {$group: {_id: $_id, borrowCount: {$sum: 1}, title: {$first: $title}, authors: {$first: $authors}}}, {$sort: {borrowCount: -1}}, {$limit: 10} ])5.2 借閱趨勢(shì)圖按日統(tǒng)計(jì)近 7 天借閱量補(bǔ)零、格式化需求生成折線圖數(shù)據(jù)X 軸為日期2024-05-01到2024-05-07Y 軸為當(dāng)日借閱次數(shù)。難點(diǎn)是 MongoDB 默認(rèn)不返回“0 借閱”的日期需前端補(bǔ)零更優(yōu)解是用$dateToString$range在聚合中生成完整日期序列。public ListDailyBorrow getDailyBorrowTrend() { // 步驟1生成近7天日期數(shù)組ISO格式 LocalDate today LocalDate.now(); ListLocalDate dateList Stream.iterate(today, d - d.minusDays(1)) .limit(7) .collect(Collectors.toList()); Collections.reverse(dateList); // 保證從早到晚 // 步驟2構(gòu)建聚合簡化版先查再補(bǔ)零適合課設(shè) // 更高階寫法見下方“玄學(xué)技巧” ListDailyBorrow rawStats mongoTemplate.aggregate( Aggregation.newAggregation( Aggregation.unwind(borrowRecords), Aggregation.match(Criteria.where(borrowRecords.borrowDate) .gte(Date.from(today.minusDays(6).atStartOfDay(ZoneId.systemDefault()).toInstant())) .lt(Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()))), Aggregation.group( Aggregation.fields() .and(DateOperators.DateToString.dateOf(borrowRecords.borrowDate).toString(%Y-%m-%d)).as(date) ).count().as(count) ), books, DailyBorrow.class ).getMappedResults(); // 步驟3按日期補(bǔ)零將 rawStats 轉(zhuǎn)為 Map再遍歷 dateList 填充 MapString, Integer statMap rawStats.stream() .collect(Collectors.toMap(DailyBorrow::getDate, DailyBorrow::getCount, (a,b)-a)); return dateList.stream() .map(d - { String dateStr d.toString(); // 2024-05-01 return new DailyBorrow(dateStr, statMap.getOrDefault(dateStr, 0)); }) .collect(Collectors.toList()); }玄學(xué)技巧高階用$range$map在聚合中生成日期序列再$lookup關(guān)聯(lián)借閱數(shù)據(jù)徹底避免前端補(bǔ)零。但課設(shè)階段上述“查補(bǔ)”方案更易懂、易調(diào)試。真正上線系統(tǒng)才值得投入精力寫$range版本。5.3 表格聚合管道常用操作符與課設(shè)對(duì)應(yīng)場(chǎng)景操作符語法示例課設(shè)中典型用途注意事項(xiàng)$unwind{$unwind: $borrowRecords}拆解借閱記錄數(shù)組為后續(xù)統(tǒng)計(jì)鋪路若某圖書無借閱記錄該文檔會(huì)被丟棄需$ifNull處理$group{$group: {_id: $category, count: {$sum: 1}}}統(tǒng)計(jì)各分類圖書數(shù)量_id可為字段名、表達(dá)式或null全表聚合$project{$project: {title: 1, authors: 1, score: {$meta: textScore}}}控制返回字段添加文本檢索得分$meta: textScore僅在text查詢中有效$facet{$facet: {top10: [{$sort: {count:-1}}, {$limit:10}], total: [{$count: count}]}}一次聚合返回多個(gè)維度結(jié)果如熱門榜總數(shù)內(nèi)存消耗大數(shù)據(jù)量大時(shí)慎用$lookup{$lookup: {from: users, localField: borrowerId, foreignField: _id, as: borrowerInfo}}關(guān)聯(lián)其他集合課設(shè)未用但擴(kuò)展性強(qiáng)MongoDB 3.2 支持類似 SQL LEFT JOIN從那以后我每次接到課設(shè)類 MongoDB 項(xiàng)目都會(huì)先花 10 分鐘檢查三件事JDK 版本是否鎖死在 11application.yml的authSource是否與用戶創(chuàng)建庫一致以及Book.java的Field是否全部顯式聲明。這三處占了 80% 的啟動(dòng)失敗原因。至于聚合管道我習(xí)慣先在 MongoDB Shell 里寫好aggregate([...])驗(yàn)證邏輯再翻譯成 Java 的Aggregation對(duì)象——畢竟黑匣子越少debug 越快。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取