mongo数据库中获取嵌套指定字段方式

mongo数据库中获取嵌套指定字段方式

场景

在mongo数据库中,由于内存等性能原因不能获取整个文档,且需要获取文档中嵌套的部分字段值(其余字段值不需要),并将字段提取到嵌套外的情况下,通过MongoTemplate在软件层面获取指定字段的方法。

数据结构

假设需要在下列文档中获取_idnameageaddress.cityaddress.zipcode字段,无需获取address.street字段

mongo数据库中格式如下

json 复制代码
{
    "_id" : "1",
    "name" : "zhangsan",
    "age" : NumberInt(18),
    "address" : {
        "city" : "北京市",
        "street" : "海淀街道",
        "zipcode" : [
            "100080",
            "100000"
        ]
    },
    "_class" : "com.example.demo.dto.User"
}

Java中类结构如下

java 复制代码
public class User {
    @Id
    public String id;
    public String name;
    public Integer age;
    public Address address;
}

public class Address {
    public String city;
    public String street;
    public List<String> zipcode;
}

方法

通过创建扩展类对象,结合聚合管道方式进行解决核心逻辑如下

  1. 创建用户扩展类对象,并声明需要脱离嵌套的字段

    java 复制代码
    public class UserExtend extends User{
        List<String> zipcode;
    }
  2. 使用聚合管道

    java 复制代码
    //构建基础聚合管道
    List<AggregationOperation> operations = new ArrayList<>();
    operations.add(Aggregation.project(new String[]{"_id","name", "age"})
            .and("address.city").as("city")
            .and("address.zipcode").as("zipcode")
    );
    //其他还可按需加入
    //查询
    Aggregation aggregation = Aggregation.newAggregation(operations);
    AggregationResults<UserExtend> results = mongoTemplate.aggregate(
            aggregation,
            "userInfo",
            UserExtend.class
    );
    List<UserExtend> mappedResults = results.getMappedResults();

完整代码逻辑如下

代码

controller层

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    UserService userService;

    @RequestMapping(value = "/findWithoutStreet", method = RequestMethod.POST)
    public Result getUserWithoutStreet(@RequestParam String id) {
        return userService.getUserWithoutStreet(id);
    }

}

service层

java 复制代码
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserDao userDao;

    @Override
    public Result getUserWithoutStreet(String id) {
        User user = userDao.getUserWithoutStreet(id);
        return Result.success(user);
    }
    
}

dao层

java 复制代码
@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public User getUserWithoutStreet(String id) {
        Query query = new Query();
        query.addCriteria(
                Criteria.where("_id").is(id)
        );
        //构建基础聚合管道
        List<AggregationOperation> operations = new ArrayList<>();
        operations.add(Aggregation.project(new String[]{"_id","name", "age"})
                .and("address.city").as("city")
                .and("address.zipcode").as("zipcode")
        );
        //其他还可按需加入

        //查询
        Aggregation aggregation = Aggregation.newAggregation(operations);
        AggregationResults<UserExtend> results = mongoTemplate.aggregate(
                aggregation,
                "userInfo",
                UserExtend.class
        );
        List<UserExtend> mappedResults = results.getMappedResults();
        return mappedResults.get(0);
    }
}

以上为针对该问题的逻辑代码

相关推荐
独泪了无痕4 分钟前
SpringBoot Event事件机制,轻松实现业务解耦
spring boot·后端·spring
悲且狂1 小时前
SpringBoot项目改造注意事项(旧项目框架复用)
java·spring boot·后端
敲代码的嘎仔1 小时前
28届后端开发-海康威视日常实习一面(已OC)
java·开发语言·后端·面试·海康威视·实习·大厂
IT_陈寒2 小时前
JavaScript数组排序踩的坑,差点让我加班到凌晨
前端·人工智能·后端
接着奏乐接着舞。2 小时前
【2026】73道Redis 常见面试题与参考答案
数据库·redis·后端·缓存
掘金者阿豪3 小时前
Seedance 2.0/2.5 虚拟素材能跨 Key 共用吗?一次讲清 Asset ID、账号隔离与 SaaS 素材架构
前端·后端
程序员黎剑3 小时前
Spring-Bean生命周期-构造器访问Autowired字段为null
java·后端·spring
泡海椒3 小时前
JQuick-Curl 拦截器实战:统一 Token、日志、请求预处理,让第三方接口调用真正工程化
后端
东方小月3 小时前
一篇文章带你深入拆解Skill的本质与工程实现,让你不再滥用Skill
前端·人工智能·后端