插入嵌入文档而不阅读整个文档 - spring,mongo

Posted

技术标签:

【中文标题】插入嵌入文档而不阅读整个文档 - spring,mongo【英文标题】:Insert embeded document without reading whole document - spring, mongo 【发布时间】:2020-09-22 03:58:21 【问题描述】:

我有这个factory 收藏:

@Document(collection = "factory")
public class Factory

    Private List<Product> products;


Product 作为产品嵌入。 当我必须向现有工厂添加产品时:

@Autowired
private FactoryRepository factoryRepository;

public void addProduct(Long id, Product product) 
    Factory f = factoryRepository.findById(id);
    f.addProduct(product);
    factoryRepository.save(f);


但是,问题是产品是一个包含一组重属性的大型对象,而工厂可以拥有 2000 个产品

因此,检索到的工厂会导致大量内存消耗,尽管在此阶段不需要。有没有办法在不读取整个对象的情况下直接将新产品对象附加到工厂文档中?


编辑:

至于cmets,我试过了:

public void addProduct(Long id, Product product) 
        Document find = new Document("_id",id);
        Document listItem = new Document("products",product);
        Document push = new Document("$push", listItem);
        collection.updateOne(find,push);
       

这给出了错误:

org.bson.codecs.configuration.CodecConfigurationException: 
Can't find a codec for class product

所以我修改为在推送之前将其转换为字符串:

public void addProduct(Long id, Product product) 
        Document find = new Document("_id",id);
        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        Document listItem = new Document("products",ow.writeValueAsString(product));
        Document push = new Document("$push", listItem);
        collection.updateOne(find,push);
     

这个推送对象正确但是在读取时:

org.springframework.core.convert.ConverterNotFoundException: 
No converter found capable of converting from type [java.lang.String] to type [Product]

不过,我在这里无处。有关解决此问题的任何想法?

【问题讨论】:

您可以尝试为这种情况实施不同的更新操作。这能解决你的问题吗? ***.com/questions/15436542/… 不,直接将此产品对象转换为文档非常困难。寻找自动映射属性的解决方案 您的集合factory 中有多少Factory 对象?是否只有一家工厂拥有所有产品?如果是这样,您应该使用集合 products 代替,您可以在其中直接插入 Product 对象。 可以有大约 1200 个工厂对象 你不关心并发更新吗?如果 2 个不同的线程同时将产品推送到同一工厂,则有可能丢失其中一个更新。 $push 解决了这两个问题。 【参考方案1】:

您应该使用 MongoTemplate 通过推送更新产品以添加到现有产品。类似的东西

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

@SpringBootApplication
public class So62173077Application 

    public static void main(String[] args) 
        SpringApplication.run(So62173077Application.class, args);
    

    @Autowired
    private MongoTemplate mongoTemplate;

    @Document(collection = "factory")
    public class Factory
    
        private Long id;
        private List<Product> products;

    

    public Long createFactory() 
        Factory factory = new Factory();
        factory.id = 1L;
        return mongoTemplate.insert(factory).id;
    

    public void addProduct(Long id) 
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        Product product = new Product();
        product.name = "***";
        update.push("products", product);
        mongoTemplate.updateFirst(query, update, Factory.class);
    

    private class Product 
        private String name;
    

    @Bean
    public ApplicationRunner runner() 
        return args -> 
            //Long id = createFactory();
            addProduct(1L);

        ;
    


【讨论】:

这看起来不错 :D 。我想知道,这可以使用存储库接口来实现(即:自定义查询) 无法使用存储库接口进行增量更新。【参考方案2】:

可能不鼓励使用 MongoDB 大型数组(获取、原子操作、复杂查询)。

取决于您的需求,但我建议您在全新的“产品”集合中处理产品。您当前的问题也将得到解决。

问候。

【讨论】:

以上是关于插入嵌入文档而不阅读整个文档 - spring,mongo的主要内容,如果未能解决你的问题,请参考以下文章

HIbernate 批量插入或更新在 Spring Boot 中不起作用

将外部 PDF 插入 Prawn 生成的文档

Spring Data Mongo |无法授权插入没有字符串类型的 system.indexes 文档

Muenchian Grouping - 在一个节点内分组,而不是在整个文档内

在猫鼬中仅更改整个嵌入式文档数组的一个字段

在猫鼬中仅更改整个嵌入式文档数组的一个字段