Spring + MongoDB标记@Query,$ group无效

时间:2016-08-09 17:28:47

标签: spring mongodb

注意:向下看以查看已编辑的信息。

我试图模仿这个查询:

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.

3 个答案:

答案 0 :(得分:0)

根据我发现的信息,您无法在MongoRepository方法上执行@Query的复杂操作。在这种情况下,您需要创建一个类并使用mongoTemplate实现您的comptarSentiments()方法,以使用您的聚合函数查询数据存储。然后创建一个暴露REST端点并让它调用存储库的控制器类。

一旦你在Mongo中进行复杂的查询,就会失去@RepositoryRestResource的易用性,并且必须自己回到将REST端点连接到存储库。

https://tour.golang.org/flowcontrol/8

Spring Data REST : custom query for MongoDB repository

答案 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);