我有以下问题。假设我有以下模型对象:
class Person {
String id;
String firstName;
String lastName;
Map<String, String> properties;
}在属性映射中,您可以插入任何类型的属性,没有约束。
上面的对象保存在一个MongoDB中,如下所示:
public interface PersonRepo extends MongoRepository<Person, String> {
}当一个人被保存到存储库中时,Map<String, String> properties就会扁平化。例如,如果我们有以下对象:
Person: {
id := 1;
firstName := John,
lastName := Doe,
properties := {
age: 42
}
}保存在MongoRepository中的文档如下:
Person: {
id := 1;
firstName := John,
lastName := Doe,
age := 42
}现在我的问题是,如果对象是否具有特定属性,则必须基于(例如)查找对象。让我说,我想要所有已经为其定义了年龄财产的人。一个重要的附加要求是,我应该返回一个分页的结果。
我试过用
findAll(Example<Person> example, Pageable pageable)但由于某种原因,这种做法行不通。我怀疑我的模型对象和MongoDB文档有不同的结构。
我也尝试过使用QueryDsl (这里有一个例子:http://www.baeldung.com/queries-in-spring-data-mongodb),但是也没有成功,而且对我来说,这个解决方案也不是优雅的(必须处理生成的类和类似的类)。另外,我觉得它不会工作,因为我的Map<String, String> properties对象成员)。
我想到的另一个解决方案是具有以下功能,并且非常优雅:
@Query(value = "?0")
Page<Query> findByQuery(String query, Pageable pageable)在这种情况下,我可以手动构造查询,也不必硬编码运行搜索的密钥。我现在的问题是,如何才能将查询值精确地设置为我的第一个参数?在上面显示的示例中,我得到以下错误
java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject另一个解决方案是使用mongoTemplate和Criteria查询,如下面的示例所示:
final Query query = new Query();
query.addCriteria(Criteria.where("age").regex(".*"));
mongoTemplate. find(query, Person.class);此解决方案的问题是,它返回对象列表而不是分页结果。如果我添加query.with(new PageRequest(3, 2));,它也返回一个特定的页面,但是在这种情况下,我不能手动构造“分页”结果,因为我不知道元素的总数。
你还有其他能帮我的主意吗?
提前感谢!
发布于 2017-07-31 09:22:02
贝娄是我想出的解决办法。因此,简单地回顾一下,我遇到的问题是,我无法执行给定查询对象作为输入的查询,从而提高了过滤标准的灵活性。解决方案非常简单,我只需仔细阅读文档:)。
扩展MongoRepository并添加自定义函数:
@NoRepositoryBean
public interface ResourceRepository<T, I extends Serializable> extends MongoRepository<T, I> {
Page<T> findAll(Query query, Pageable pageable);
}为该接口创建一个实现:
public class ResourceRepositoryImpl<T, I extends Serializable> extends SimpleMongoRepository<T, I> implements ResourceRepository<T, I> {
private MongoOperations mongoOperations;
private MongoEntityInformation entityInformation;
public ResourceRepositoryImpl(final MongoEntityInformation entityInformation, final MongoOperations mongoOperations) {
super(entityInformation, mongoOperations);
this.entityInformation = entityInformation;
this.mongoOperations = mongoOperations;
}
@Override
public Page<T> findAll(final Query query, final Pageable pageable) {
Assert.notNull(query, "Query must not be null!");
return new PageImpl<T>(
mongoOperations.find(query.with(pageable), entityInformation.getJavaType(), entityInformation.getCollectionName()),
pageable,
mongoOperations.count(query, entityInformation.getJavaType(), entityInformation.getCollectionName())
);
}
}将实现设置为默认的MongoRepository实现:
@EnableMongoRepositories(repositoryBaseClass = ResourceRepositoryImpl.class)
public class MySpringApplication {
public static void main(final String[] args) {
SpringApplication.run(MySpringApplication.class, args);
}
}为自定义对象创建一个存储库:
public interface CustomObjectRepo extends ResourceRepository<CustomObject, String> {
}现在,如果您想要保存在mongo文档存储中的多个对象,那么定义一个扩展ResourceRepository的接口就足够了(如步骤4所示),并且您可以使用Page<T> findAll(Query query, Pageable pageable)自定义查询方法。我发现这个解决方案是我尝试过的最优雅的解决方案。
如果您有任何改进的建议,请与社区分享。
你好,克里斯蒂安
发布于 2017-07-27 20:08:57
我最近也遇到了类似的情况。使用Clazz代替我的域类,下面是我所做的工作:
long count = mongoTemplate.count(query, clazz.class);
query.with(pageable);
List<Clazz> found = mongoTemplate.find(query, clazz.class);
Page<Clazz> page = new PageImpl<T>(found, pageable, count);我使用的是spring starter mongodb:1.5.5和Query + MongoTemplate处理分页。因此,首先,我得到了与查询匹配的所有文档的完整计数。然后,我再次使用peageable进行搜索,搜索再次跳过和限制(我知道,效率不高)。回到Controller时,您可以使用PagedResourcesAssembler's toResource( paging )方法将其封装在分页超链接中。
public ResponseEntity search(@Valid @RequestBody MyParams myParams, Pageable pageable, PagedResourcesAssembler assembler){
Page<Clazz> page= searchService.search(myParams, pageable, Clazz.class);
PagedResources<Clazz> resources = assembler.toResource(page);
return new ResponseEntity<>(resources, HttpStatus.OK);
}发布于 2021-10-06 19:50:09
有一种非常简单的方法可以做到这一点,类似于您的代码:
@Query(value = "?0")
Page<Query> findByQuery(String query, Pageable pageable)但是将查询作为BSONObject而不是字符串传递。
@Query("?0")
Page<Query> findByQuery(BSONObject query, Pageable pageable)https://stackoverflow.com/questions/44151977
复制相似问题