How to Get Only Matched Result from An Array Field of Document in Mongo Using Spring Data

ε祈祈猫儿з 提交于 2019-11-29 07:47:54

The named query works as it should be. You are not explicitly saying that you want only a portion of document so query returns whole document. To achieve that you cannot use named queries (see @alexefimov answer for using named queries with help of @Query annotation) but you can use MongoTemplatebeside of MongoRepository. to do that you have to make some changes:

First your repository should be like this:

public interface HotelRepository extends MongoRepository<Hotel, String>, MongoTemplateRepository {
    // You can continue to write your named queries here. Spring will create that.
}

MongoTemplateRepository:

public interface MongoTemplateRepository {
    // You will write your queries which will use mongoTemplate here. 
    List<Hotel> findByReviewsUserName(String userName);
}

For implementation of MongoTemplateRepository methods, you will write a new class. The important thing here is that you should named this class your repository class name + Impl. Otherwise spring-data cannot find where your methods implementation those defined in MongoTemplateRepository. So your implementation class's name should be HotelRepositoryImpl

public class HotelRepositoryImpl implements MongoTemplateRepository {

    @Autowired
    private MongoTemplate mongoTemplate; // we will use this to query mongoDb

    @Override
    public List<Hotel> findByReviewsUserName(String userName) {
        Query query = new Query();
        query.addCriteria(Criteria.where("reviews.username").is(userName));
        query.fields().include("reviews.$");
        return mongoTemplate.find(query, Hotel.class);
    }
}

Usage:

hotelRepository.findByReviewsUserName("userName");

As you can see in codes we can .include() or .excludefields for the query. While you want to include just matched part of an array field, we use $operator with array field name.

Conclusion: You can still use spring-data well supported named queries and additionally if you need aggregation or some complex queries for sub documents that a named query cannot be built by spring, you can do it in your newly created mongoTemplate repository class. And you can access all of your repository methods from HotelRepository.

Great answer from @barbakini, but that also can be done without creating custom repository implementation with Criteria, just 'describe' which fields you would like to get, where 0 - .exclude, 1 - .include(

@Query(fields = "{ '_id': 0, 'reviews.$': 1 }")
List<Hotel> findByReviewsUserName(String userName);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!