Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make mongo query in spring where Document contain array

I am using spring and mongo for API developemt with the following document structure:

Document-1
myId:1
array:['abc','jkl','xyz']

Document-2
myId:3
array:['qwe','mnp','xyz']

Document-3
myId:3
array:['ped','abc','xyz']

My url : localhost:8080/array=xyz
expected : document-1,document-2,document-3

My url: localhost:8080/array=xyz,abc
exoected: document-1,document-3

In short I want all the documents in result which contains all the comma separated array variable.

Is there ary inbuild support that spring provides for this like @Query annotation?

Or How can I acheive this?

like image 907
i_lalit Avatar asked Oct 20 '15 10:10

i_lalit


People also ask

How do I query an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

Can we store array in MongoDB?

One of the benefits of MongoDB's rich schema model is the ability to store arrays as document field values. Storing arrays as field values allows you to model one-to-many or many-to-many relationships in a single document, instead of across separate collections as you might in a relational database.

How do I add an array of strings in MongoDB?

ArrayList<String> stringArray = new ArrayList<String>(); BasicDBObject document = new BasicDBObject(); document. put("master", stringArray); db. getCollection("master"). insert(document);

What is $Push in MongoDB?

If the field is absent in the document to update, $push adds the array field with the value as its element. If the field is not an array, the operation will fail. If the value is an array, $push appends the whole array as a single element. To add each element of the value separately, use the $each modifier with $push .


1 Answers

You essentially want to use the $all operator to get the desired results. In the mongo shell, the following operation will bring the documents:

Populate test collection

db.test.insert([
    {
        _id: 1,
        myId: 1,
        array: ['abc','jkl','xyz']
    },
    {
        _id: 2,
        myId: 3,
        array: ['qwe','mnp','xyz']
    },
    {
        _id: 3,
        myId: 3,
        array:['ped','abc','xyz']
    }
])

Run operations

> db.test.find({"array": { "$all": ["xyz"] }})
{ "_id" : 1, "myId" : 1, "array" : [ "abc", "jkl", "xyz" ] }
{ "_id" : 2, "myId" : 3, "array" : [ "qwe", "mnp", "xyz" ] }
{ "_id" : 3, "myId" : 3, "array" : [ "ped", "abc", "xyz" ] }

> db.test.find({"array": { "$all": ["abc", "xyz"] }})
{ "_id" : 1, "myId" : 1, "array" : [ "abc", "jkl", "xyz" ] }
{ "_id" : 3, "myId" : 3, "array" : [ "ped", "abc", "xyz" ] }

As with the @Query annotation in Spring Data MongoDB, I haven't tested this but you may want to try the following custom query implementation example

@Document(collection="test")
class Test {
    int myId;
    String[] array;
}

public interface TestRepository extends MongoRepository<Test, Integer> {
    @Query(value = "{ 'array' : {$all : [?0] }}")
    public List<Test> findAnyOfTheseValues(String[] arrayValues);
}

If the above doesn't work for you, you may want to create a custom interface and your implementation class to execute the custom query. For example, create an interface with a name that appends Custom:

public interface TestRepositoryCustom {
    public List<Test> findAnyOfTheseValues(String[] arrayValues); 
}

Modify the TestRepository and add the TestRepositoryCustom interface to be extended:

@Repository
public interface TestRepository extends TestRepositoryCustom, MongoRepository {

}

Create your implementation class to implement the methods defined in TestRepositoryCustom interface.

public class TestRepositoryImpl implements TestRepositoryCustom {

    @Autowired
    MongoTemplate mongoTemplate;

    @Override
    public List<Test> findAnyOfTheseValues(String[] arrayValues) {
        return mongoTemplate.find(
            Query.query(Criteria.where("array").all(arrayValues)), Test.class);
    }
}
like image 72
chridam Avatar answered Oct 19 '22 07:10

chridam