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

30 阅读1分钟

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

场景

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

数据结构

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

mongo数据库中格式如下

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

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. 创建用户扩展类对象,并声明需要脱离嵌套的字段

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

    //构建基础聚合管道
    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层

@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层

@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层

@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);
    }
}

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