如何用MongoDB Java/Kotlin驱动获取文档数组最后一项(不加载全量数据)
用MongoDB Kotlin驱动仅获取文档数组最后一项(避免加载整个文档/数组)
你当前的写法会把整个LiveChatRoom文档和完整的messages数组全部加载到内存中,碰到超大数组时效率极低。下面两种方法可以实现仅获取数组最后一项,无需加载整个文档和数组:
方法一:使用投影操作符$slice
利用MongoDB的$slice投影操作符,直接指定只返回数组的最后1个元素:
import org.bson.Document import com.mongodb.client.model.Filters // 定义投影规则:仅返回messages数组的最后一项 val projection = Document("messages", Document("\$slice", -1)) val lastMessage = rooms.find(Filters.eq("userId", userId)) .projection(projection) .singleOrNull() ?.messages ?.firstOrNull() // 因为$slice返回的是含单个元素的数组,所以取第一个元素
如果使用KMongo的DSL语法,代码可以更简洁:
import org.litote.kmongo.* val lastMessage = rooms.find(LiveChatRoom::userId eq userId) .projection(LiveChatRoom::messages slice -1) .singleOrNull() ?.messages ?.firstOrNull()
方法二:使用聚合管道直接提取目标元素
通过聚合管道的$last操作符直接提取数组最后一项,最终返回单个ChatMessage对象:
import org.litote.kmongo.* val lastMessage = rooms.aggregate<ChatMessage>( match(LiveChatRoom::userId eq userId), project(Document("lastMessage", Document("\$last", "\$messages"))), replaceRoot("\$lastMessage") ).singleOrNull()
这种方式会直接返回最后的消息对象,不需要额外处理数组元素,逻辑更直观。
两种方法对比
- 投影法适合需要保留文档其他字段的场景,或者仅需快速获取数组最后一项的需求;
- 聚合法更直接,直接返回目标对象,无需处理数组包装。
内容的提问来源于stack exchange,提问作者Eel
相关产品推荐
相关产品推荐

