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

Spring Boot嵌入式MongoDB:Java创建函数、调用及批量数据导入问题

解决方案

一、批量插入文档优化

不用逐个插入,直接用MongoTemplate.insertAll()批量处理文档集合即可:

// 示例:批量插入自定义实体类文档
List<YourEntity> entityList = Arrays.asList(new YourEntity("val1"), new YourEntity("val2"));
mongoTemplate.insertAll(entityList);

如果是JSON格式的批量数据,转成Document集合后用insertMany效率更高:

// 从JSON数组转成Document列表
String jsonBatch = "[{\"name\":\"test1\"}, {\"name\":\"test2\"}]";
List<Document> docList = Arrays.asList(new ObjectMapper().readValue(jsonBatch, Document[].class));
mongoTemplate.getCollection("target-collection").insertMany(docList);

二、在system.js中创建序列函数

system.js就是MongoDB存储服务器端JS函数的普通集合,直接往里面插入函数文档即可,两种实现方式:

方式1:直接操作system.js集合(推荐)

// 把函数代码写成字符串
String funcCode = "function getNextSequence(seqName) { " +
        "var seqDoc = db.dbSequence.findAndModify({ " +
        "query: {seq: seqName}, " +
        "update: {$inc: {value: 1}}, " +
        "new: true " +
        "}); " +
        "return seqDoc.value; " +
        "}";

// 构造要插入的文档,_id对应函数名
Document funcDoc = new Document("_id", "getNextSequence")
        .append("value", funcCode);

// 用replaceOne+upsert,不存在就插入,存在就更新
mongoTemplate.getCollection("system.js").replaceOne(
        Filters.eq("_id", "getNextSequence"),
        funcDoc,
        new ReplaceOptions().upsert(true)
);

方式2:执行MongoDB命令(注意:eval在4.2+版本已弃用)

MongoDatabase db = mongoTemplate.getMongoDbFactory().getMongoDatabase();
Document command = new Document("eval",
        "db.system.js.save({_id: 'getNextSequence', value: function getNextSequence(seqName) { " +
        "var seqDoc = db.dbSequence.findAndModify({query: {seq: seqName}, update: {$inc: {value: 1}}, new: true}); " +
        "return seqDoc.value; " +
        "}})"
);
db.runCommand(command);

三、调用序列函数的方法

方式1:用eval调用(不推荐,已弃用)

MongoDatabase db = mongoTemplate.getMongoDbFactory().getMongoDatabase();
Document cmd = new Document("eval", "getNextSequence('user-id-seq')");
Document result = db.runCommand(cmd);
Long nextSeq = result.getLong("retval");

方式2:直接在Java里实现逻辑(推荐,无版本依赖)

没必要依赖服务器端函数,直接在Java里写findAndModify逻辑更稳妥:

// 查询条件:匹配序列名称
Query query = Query.query(Criteria.where("seq").is("user-id-seq"));
// 更新操作:value自增1
Update update = new Update().inc("value", 1);
// 配置:返回更新后的新文档
FindAndModifyOptions options = FindAndModifyOptions.options().returnNew(true);

// 执行操作,返回更新后的序列文档
DbSequence seqDoc = mongoTemplate.findAndModify(query, update, options, DbSequence.class);
Long nextSeq = seqDoc.getValue();

对应的DbSequence实体类:

@Document(collection = "dbSequence")
public class DbSequence {
    @Id
    private String id;
    private String seq;
    private Long value;

    // 构造器、getter、setter
    public DbSequence(String seq, Long value) {
        this.seq = seq;
        this.value = value;
    }
}

方式3:聚合中调用(MongoDB 4.4+支持)

如果要在聚合管道里使用这个函数,用$function操作符:

Aggregation agg = Aggregation.newAggregation(
        Aggregation.project()
                .and(Aggregation.function(
                        "getNextSequence",
                        Arrays.asList("user-id-seq"),
                        Long.class
                )).as("nextSequence")
);
AggregationResults<Document> results = mongoTemplate.aggregate(agg, "your-collection", Document.class);
Long nextSeq = results.getMappedResults().get(0).getLong("nextSequence");

四、初始化时机

把这些初始化逻辑放在测试类的@BeforeAll或者@BeforeEach方法中,确保测试开始前完成所有准备:

@SpringBootTest
class YourTestClass {

    @Autowired
    private MongoTemplate mongoTemplate;

    @BeforeAll
    static void initTestData(@Autowired MongoTemplate mongoTemplate) {
        // 初始化dbSequence的初始值(比如用户序列从0开始)
        mongoTemplate.insert(new DbSequence("user-id-seq", 0L), "dbSequence");
        // 批量插入测试文档
        // 创建system.js函数
    }
}

内容的提问来源于stack exchange,提问作者pagurix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 06:15:40