Reputation: 11052
I have a List
of an object and I need to perform a query in Morphia
to get the unique result from another embedding List
of String
in given object.
@Entity
public class Fruits {
@NotNull private Long id;
@NotNull private List<String> categories;
}
Fruits:
{[
"id": 1234566,
"categories": ["A", "B", "C", "D"]
],
[
"id": 32434,
"categories": ["A", "C", "E", "F"]
],
[
"id": 32434,
"categories": ["A", "L", "M", "N"]
]
}
The result of aggregation supposed to be:
[A,C,B,D,E,F,L,M,N]
The output is in sorted form. How can I achieve this in morphia? I tried to search on official documentation but couldn't find the hint.
Any help or hint would be appreciable. Thanks
List<Fruits> fruitList = fruitControllerDao.search(fruitList);
List<Category> categories = new ArrayList<>();
datastore.createAggregation(Fruits.class)
.unwind("categories")
.group(Group.id(Group.grouping("categories")))
.sort(Sort.ascending("_id.categories"))
.project(Projection.projection("_id").suppress(),
Projection.projection("categories", "_id.categories"))
.aggregate(Category.class).forEachRemaining(categories::add);
and I have created
class Category {
private String category;
}
Data in fruitList
is unusable and I need to apply aggregation
on the fruitList
(Checkout the JSON Format) itself.
Upvotes: 1
Views: 3019
Reputation: 75934
You can use below code to get unique & sort categories using aggregation pipeline.
Prepare Query Filter:
Query<Fruits> query = datastore.createQuery(Fruits.class);
Iterator<Fruits> fruitIterator = fruitList .iterator();
CriteriaContainer orQuery = query.or();
while(fruitIterator.hasNext()) {
Fruits fruit = fruitIterator.next();
orQuery.add(query.and(query.criteria("id").equal(fruit.getId()), query.criteria("categories").equal(fruit.getCategories())));
}
The below query $matches
on query filter and $unwinds
the categories
followed by $group
to remove the duplicates and sorting. The last step is to read the value from grouping stage and $project
into category field.
List<Category> categories = new ArrayList<>();
datastore.createAggregation(Fruits.class)
.match(query)
.unwind("categories")
.group(Group.id(Group.grouping("categories")))
.sort(Sort.ascending("_id.categories"))
.project(Projection.projection("_id").suppress(), Projection.projection("category", "_id.categories"))
.aggregate(Category.class).forEachRemaining(categories::add);
class Category {
private String category;
}
Update:
Mongo Shell Query
[{ "$match" : { "$or" : [ { "$and" : [ { "_id" : 1234566} , { "categories" : [ "A" , "B" , "C" , "D"]}]} , { "$and" : [ { "_id" : 32434} , { "categories" : [ "A" , "C" , "E" , "F"]}]} , { "$and" : [ { "_id" : 32434} , { "categories" : [ "A" , "L" , "M" , "N"]}]}]}}, { "$unwind" : "$categories"}, { "$group" : { "_id" : { "categories" : "$categories"}}}, { "$sort" : { "_id.categories" : 1}}, { "$project" : { "_id" : 0 , "category" : "$_id.categories"}}]
Upvotes: 2