注意:向下看以查看已编辑的信息。
我试图模仿这个查询:
db.sentiments.aggregate([
{"$group" : {_id:{theme_id:"$theme",sentiment_id:"$sentiment"}, count:{$sum:1}}},
{"$sort":{"_id.theme_id":1}} ])
这是我为了模仿它而生成的代码:
@RepositoryRestResource(collectionResourceRel = "sentiments", path = "sentiments")
public interface SentimentsRepository extends MongoRepository<Sentiments, String> {
Long countByTheme(@Param("theme") String theme);
@Query(value ="[\n" +
" {\"$group\" : {_id:{theme_id:\"$theme\",sentiment_id:\"$sentiment\"}, count:{$sum:1}}},\n" +
"\t{\"$sort\":{\"_id.theme_id\":1}}\n" +
"]",count = true)
List<Object> comptarSentiments();
} 那么这段代码正在给我这个错误:
"exception": "org.springframework.data.mongodb.UncategorizedMongoDbException",
"message": "Can't canonicalize query: BadValue unknown operator: $group; nested exception is com.mongodb.MongoException: Can't canonicalize query: BadValue unknown operator: $group",
实际上我是指使用Spring的原因所以我很失落,有谁知道我应该怎么做?
感谢和抱歉我的英语不好,而不是我的母语。
[编辑] ---------------------------------------- 就像Shawn Clark写的评论一样,不可能这样做,为了实现这一点,你需要创建一个customRepository。
What's the difference between Spring Data's MongoTemplate and MongoRepository?
我一直试图这样做,但有些事情似乎不正确,这是我的新代码:
@RepositoryRestResource(collectionResourceRel = "sentiments", path = "sentiments")
public interface SentimentsRepository extends CrudRepository<Sentiments, String>, CustomSentimentsRepository {
//Other methods...
}
public interface CustomSentimentsRepository {
List<CountResult> yourCustomMethod();
class CountResult{
String theme;
String sentiment;
int total;
}
}
public class SentimentsRepositoryImpl implements CustomSentimentsRepository {
private final MongoOperations operations;
@Autowired
public SentimentsRepositoryImpl(MongoOperations operations) {
Assert.notNull(operations, "MongoOperations must not be null!");
this.operations = operations;
}
@Override
public List<CountResult> yourCustomMethod(){
Aggregation agg = Aggregation.newAggregation(
Aggregation.group("theme","sentiment").count().as("total"),
Aggregation.project("theme","sentiment").and("total").previousOperation(),
Aggregation.sort(Sort.Direction.DESC, "theme")
);
//Convert the aggregation result into a List
AggregationResults<CountResult> groupResults
= operations.aggregate(agg,"sentiments", CountResult.class);
//List<CountResult> result = groupResults.getMappedResults();
return groupResults.getMappedResults();
}
}
我甚至无法对此代码进行验证,而且我总是得到404.
答案 0 :(得分:0)
根据我发现的信息,您无法在MongoRepository方法上执行@Query的复杂操作。在这种情况下,您需要创建一个类并使用mongoTemplate实现您的comptarSentiments()方法,以使用您的聚合函数查询数据存储。然后创建一个暴露REST端点并让它调用存储库的控制器类。
一旦你在Mongo中进行复杂的查询,就会失去@RepositoryRestResource的易用性,并且必须自己回到将REST端点连接到存储库。
答案 1 :(得分:0)
我终于设法解决了这个问题,看起来它与控制器和来自innerClass CountResult的属性“total”的类型有关,它需要是一个String(这个非常重要,否则是Aggregation.project将失败)。这是最终的代码:
public interface CustomSentimentsRepository {
List<CountResult> myCountGroupByThemeAndSentiment();
class CountResult{
public String theme;
public String sentiment;
public String total;
}
}
public class SentimentsRepositoryImpl implements CustomSentimentsRepository {
private final MongoTemplate mongoTemplate;
@Autowired
public SentimentsRepositoryImpl(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@Override
public List<CountResult> myCountGroupByThemeAndSentiment(){
Aggregation agg = Aggregation.newAggregation(
Aggregation.group("theme","sentiment").count().as("total"),
Aggregation.project("theme","sentiment").andInclude("total"),
Aggregation.sort(Sort.Direction.ASC,"theme","sentiment")
);
AggregationResults<CountResult> groupResults
= mongoTemplate.aggregate(agg,"sentiments", CountResult.class);
return groupResults.getMappedResults();
}
}
@RepositoryRestResource(collectionResourceRel = "sentiments", path = "sentiments")
public interface SentimentsRepository extends CrudRepository<Sentiments, String>, CustomSentimentsRepository {
//Other methods
}
@RestController
@RequestMapping(value = "sentiments/search")
public class ChartsController {
@Autowired
private SentimentsRepository sentimentsRepository;
@RequestMapping(value = "myCountGroupByThemeAndSentiment", method = RequestMethod.GET)
public ResponseEntity<?> yourCustomMethod() {
List<?> count=sentimentsRepository.myCountGroupByThemeAndSentiment();
return new ResponseEntity(count, HttpStatus.OK);
}
}
答案 2 :(得分:0)
您可以使用Spring数据mongodb 2.2.X版本中可用的@Aggrgation:
@Aggregation(pipeline = {"{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }", "{ '$sort' : { 'lastname' : -1 } }"}) List<PersonAggregate> groupByLastnameAnd(String property);