Xiran Li
Xiran Li

Reputation: 41

Sort doesn't work when user aggregation in Spring data Mongo

I am trying run a mongo aggregation on Spring data here is the sample json

{
    "id":*****
    "taskResultContent":
    [
        {
            "executionUUID":"uuid_2",
            "sequency":"1",
            "returnContent":"SUCCESS",
        },
        {
            "executionUUID":"uuid_2",
            "sequency":"2",
            "returnContent":"SUCCESS",
        }
    ]
}

here is my Mongo query

[
    {
        "$match" : {
        "_id" : ObjectId("54767c7cfda0da01d4843e93")
        }
    },
    {
        "$unwind" : "$taskResultContent"
     },
    {
        "$project" : {
            "executionUUID" : "$taskResultContent.executionUUID",
            "returnContent" : "$taskResultContent.returnContent",
            "sequency" : "$taskResultContent.sequency",
            "_id" : 0,
            "resultID" : "$_id"
    }
    },
    {
        "$match" : {
        "executionUUID" : "uuid_3"
        }
    },
    {
        "$sort" : {
        "sequency" : -1
        }
    }
]

here is my java implementation:

Aggregation agg = newAggregation(
                match(Criteria.where("_id").is(objId)),
                unwind("taskResultContent"),
                project("taskResultContent.executionUUID","taskResultContent.returnContent","taskResultContent.sequency").and("resultID").previousOperation(),
                match(Criteria.where("executionUUID").is(executionUUID)),
                sort(DESC,"sequency")
            );

Then I found a problem, the SORT doesn't work. I print out the aggregation query from java. it looks like:

    {
        "$sort": {
            "taskResultContent.sequency": -1
        }
    }

it should be "sequerycy":-1 but not "taskResultContent.sequency": -1 Does anyone meet the same issue ?

Upvotes: 2

Views: 2165

Answers (2)

max314
max314

Reputation: 21

You would new class

class SortOperationEx implements AggregationOperation {

    private final Sort sort;

    /**
     * Creates a new {@link org.springframework.data.mongodb.core.aggregation.SortOperation} for the given {@link Sort} instance.
     *
     * @param sort must not be {@literal null}.
     */
    public SortOperationEx(Sort sort) {

        Assert.notNull(sort, "Sort must not be null!");
        this.sort = sort;
    }

    public SortOperationEx (Sort.Direction direction, String... fields) {
         this(new Sort(direction, fields));
    }

    public SortOperationEx and(Sort.Direction direction, String... fields) {
        return and(new Sort(direction, fields));
    }

    public SortOperationEx and(Sort sort) {
        return new SortOperationEx(this.sort.and(sort));
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
     */
    @Override
    public DBObject toDBObject(AggregationOperationContext context) {

        BasicDBObject object = new BasicDBObject();

        for (Sort.Order order : sort) {

            // Check reference
            String prop = order.getProperty();
            object.put(prop, order.isAscending() ? 1 : -1);
        }

        return new BasicDBObject("$sort", object);
    }
}

and modify code From:

Aggregation agg = newAggregation(
                match(Criteria.where("_id").is(objId)),
                unwind("taskResultContent"),
                project("taskResultContent.executionUUID","taskResultContent.returnContent","taskResultContent.sequency").and("resultID").previousOperation(),
                match(Criteria.where("executionUUID").is(executionUUID)),
                sort(DESC,"sequency")
            );

To:

Aggregation agg = newAggregation(
                match(Criteria.where("_id").is(objId)),
                unwind("taskResultContent"),                project("taskResultContent.executionUUID","taskResultContent.returnContent","taskResultContent.sequency").and("resultID").previousOperation(),
                match(Criteria.where("executionUUID").is(executionUUID)),
                 new SortOperationEx(DESC,"sequency")
            ); 

Upvotes: 2

BatScream
BatScream

Reputation: 19700

Modify your project stage operation to use as() to project a field by some other name and then apply the sort.

..
project("taskResultContent.executionUUID").as("executionUUID").
and("taskResultContent.returnContent").as("returnContent")
...

Upvotes: 0

Related Questions