0

I have a Spring entity which looks like:

@Document(
    collection = "users"
)
public class UserEntity extends BaseEntity {
    @Indexed
    private String msisdn;
    ...
}

In the mongo shell, I'm able to find the duplicate msisdn fields via:

db.users.aggregate([
    {"$group": { "_id": "$msisdn", "count": { "$sum": 1 } } },
    {"$match": {"_id":{ "$ne": null } , "count": {"$gt": 1} } }, 
    {"$project": {"msisdn": "$_id", "_id": 0} }
]);

Which returns for example:

[
    { msisdn: '123456' },
    { msisdn: 'ABCDEF' }
]

My question is: how can I convert this aggregation to Spring?

Ariel Malka
  • 15,697
  • 6
  • 31
  • 33

1 Answers1

0

Answering my own question... The following works:

@Autowired
MongoTemplate mongoTemplate;

@Data
public class Duplicate {
    public String msisdn;
}

public List<String> getMsisdnDuplicates() {
    String query1 = "{\"$group\" : { \"_id\": \"$msisdn\", \"count\": { \"$sum\": 1 } } }";
    String query2 = "{\"$match\": {\"_id\" :{ \"$ne\" : null } , \"count\" : {\"$gt\": 1} } }";
    String query3 = "{\"$project\": {\"msisdn\" : \"$_id\", \"_id\" : 0} }";

    TypedAggregation<UserEntity> aggregation = Aggregation.newAggregation(
            UserEntity.class,
            new CustomAggregationOperation(query1),
            new CustomAggregationOperation(query2),
            new CustomAggregationOperation(query3)
    );

    List<String> results = new ArrayList<>();
    AggregationResults< Duplicate> aggregationResults = mongoTemplate.aggregate(aggregation, Duplicate.class);
    for (Duplicate result : aggregationResults.getMappedResults()) {
        results.add(result.msisdn);
    }

    return results;
}

Usage:

List<String> duplicates = getMsisdnDuplicates();
for (String duplicate : duplicates) {
    System.out.println(duplicate);
}

Results:

ABCDEF
123456

Note: the CustomAggregationOperation class is from this SO answer.

Ariel Malka
  • 15,697
  • 6
  • 31
  • 33