You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:52:27