Home > Enterprise >  Spring Data MongoDb elemMatch criteria matching all search strings
Spring Data MongoDb elemMatch criteria matching all search strings

Time:10-04

I'm having an issue with custom Spring Data queries with MongoDb and Java. I'm attempting to implement a flexible search functionality against most of the fields of the document.
This document represents a person, and it contains a set of addresses embedded in it; the address has a field that is a set of strings that are the 'street address lines'.

I started with Query By Example, and this works for the single fields. but doesn't work for other types - such as this set of strings. For these, I'm building custom criteria.

The search criteria includes a set of street lines that I would like to match against the document's lines. If every line in the search is found in the document, the criteria should be considered matching.

I've tried using elemMatch, but this doesn't quite work like I want:

    addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(addressSearch.getStreetAddressLines())));
    

This seems to match if only ONE line in the document matches the search. If I have the following document:

"streetAddressLines": [ "123 Main Street", "Apt 1" ]

and the search looks like this:

"streetAddressLines": [ "123 Main Street", "Apt 2" ]

the elemMatch succeeds, but that's not what i want.

I've also tried looping through each of the search lines, trying an elemMatch to see if each is in the document:

var addressLinesCriteriaList = new Array<Criteria>();
var streetAddressLines = address.getStreetAddressLines();
streetAddressLines.forEach(l ->  addressLinesCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().is(l))))

var matchCriteria = new Criteria.andOperator(addressLinesCriteriaList);

This doesn't seem to work. I have done some experimenting, and it may be that this doesn't seem to work: new Criteria().is(l)

I tried this, and this DOES seem to work, but I would think that it's really inefficient to create a collection for each search line:

        streetAddressLines.forEach(l ->
                {
                    var list = new ArrayList<String>();
                    list.add(l);
                    addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(l)));
                });

So I don't know exactly what's going on - does anyone have any ideas of what I'm doing wrong? Thanks in advance.

CodePudding user response:

You need to use the $all operator or the all method of Criteria class. Something along these lines:

addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines()));

If addressSearch.getStreetAddressLines returns a list, try this:

addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines().toArray(new String[0])));
  • Related