Spring data mongodb: Optional #Query parameter no longer works - spring

After upgrading to spring data mongodb 1.10.1, I am getting errors when running queries like:
#Query("{$and :["
+ "{ $or : [ { $where: '?0 == null' } , { 'field1' : ?0 } ] },"
+ "{ $or : [ { $where: '?1 == null' } , { 'field2' : ?1 } ] },"
+ "]}")
public Page<Entity> findAll(String param1, String param2)
Checking the error I see the parameter inside the where clause is not quoted and as I result I get:
org.springframework.data.mongodb.UncategorizedMongoDbException: Query
failed with error code 139 and error message 'ReferenceError:
test_param_value is not defined :
I have seen a few answers here recommending this way of handling optional parameters ((spring-data-mongo - optional query parameters?)) but it no longer works and I cannot seem to find anything in the release change log.

In case anyone else is interested, I managed to find a workaround after checking a similar ticket int the Spring Data project.
It seems the way I was checking for null parameters in the query is not a good practice. This is from a Spring developer comment: "placeholders are not designed to compose keys/values but bind parameters. Beyond that, placeholder use in quoted strings is always problematic in terms of escaping. Using SpEL should suit your needs"
So I ended up using SpEL to do the checks on parameters and it works fine. This is how it looks:
#Query("{$and :["
+ "?#{ [0] == null ? { $where : 'true'} : { 'field1' : [0] } },"
+ "?#{ [1] == null ? { $where : 'true'} : { 'field2' : [1] } },"
+ "]}")
public Page<Entity> findAll(String param1, String param2, Pageable pageable);

Related

Spring Data MongoDB SpEL Expression injection vulnerability

According to the vulnerability report (https://tanzu.vmware.com/security/cve-2022-22980), it's clearly affect for the Spel expressions like this.
#Query("{ 'userName' : ?#{?0}}")
But I just wanted to confirm, is that affect to followings too.
#Query(value = "{ '_id' : {$exists : true} }", fields = "{'_id' : 1,'customerId' : 1}")
or
#Query("{ 'name': ?0, 'customerId': ?1 }")

Spring MongoDB : querying documents with two equal fields

I want to query that returns document that two fields of it are equal
I found mongodb raw query from this question :
db.coll.find({ $where : "this.field1 == this.field2" } );
How can I perform it with spring criteria:
criteria = criteria.andOperator(
Criteria.where("successfulSent").is("true"),
Criteria.where("this.fieldOne == this.fieldTwo"));
but its not working beacuse generated query become :
{ ... "$and" : [ { "successfulSent" : "true"} , { "this.fieldOne == this.fieldOne " : { }}]}
You can try on this way:
Criteria.where("$where").is("this.field1 == this.field2")
Query toString() will be:
Query: { "$where" : "this.cts == this.uts"}, Fields: null, Sort: null

Criteria Builder query LIKE in json field

I am trying to build a query with Criteria Builder(LIKE), to look for a string in JSONARRAY field like this:
[
{
"family_class": "Electric",
"family_name": "lightBulb"
},
{
"family_class": "Others",
"family_name": "Oil"
}
]
one option would be to look for the family_name attribute, or maybe check if it contains the string there.
if (residues != null && residues.length > 0) {
List<Predicate> predicates = new ArrayList<Predicate>();
for (String residue : residues) {
predicates.add(cb.like(root.get("jsonColumn"), residue.toLowerCase()));
}
cr.select(root).where(predicates.toArray(new Predicate[] {}));
Query<SyncCollectionPoints> q = sess.createQuery(cr);
List<SyncCollectionPoints> result= q.getResultList();
This is the error i get:
Unrecognized token 'oil': was expecting ('true', 'false' or 'null')
All i want is to return the lines that have that string in the jsonColumn field.
I got it to work like this:
#Formula(value = "lower(jsonColumn::text)")
private String residuesToSearch;
just a simple cast did the trick

#Query ignored in ElasticSearch Spring java framework

I have this interface defined in Spring for querying Elascticsearch. I added #Query annotation to get some filtering done.
public interface ObjectElasticSearch extends ElasticsearchRepository<ElasticObject, String> {
#Query("{\"query\" : {\"filtered\" : {\"filter\" : { \"and\" : [ { \"term\" : { \"firstName\" : \":firstName\" }}, { \"term\" : { \"lastName\" : \"Baggins\" }} ] }}}}")
List<ElasticObject> findByDocFirstNameAndDocLastName(#Param("firstName") String firstName,
#Param("lastName") String lastName);
};
The #Query annotation gets ignored completely. As you can see I tried hardcoding last name, and it has no effect on the outcome of the query. If I delete a curly brace in the query string, I don't get any errors. Query still works, the filtering is ignored, and it returns all matches.
Can someone please help me figure out what am I doing wrong here.
Query should return a bool that in a must section can cover all your searches.
Here is my example that works for me, I have a records with startTimestamp and endTimestamp, and my method will find all of them that overlap specified timeframe + match fields by query
#Query("{\"bool\": {\"must\":["
+ " {\"range\": {\"endTimestamp\": {\"gte\": ?0}}},"
+ " {\"range\": {\"startTimestamp\": {\"lte\": ?1}}}"
+ " ], \"should\": ["
+ " {\"match\": {\"_all\": {\"query\": \"?2\", \"zero_terms_query\": \"all\"}}}"
+ " ],"
+ " \"minimum_should_match\" : 1"
+ " }"
+ "}")

MongoDB and Guid in Linq Where clause

I store an object in mongodb which contains a Guid. Mongodb converts the Guid to a binary value
{
"_id" : ObjectId("52cf4a467b302a4797db23e8"),
"name" : "test",
"guid" : new BinData(3, "qZ8PQdmDv0+K500wnj6skA=="),
}
I get an empty result set when I use the Guid in a Linq expression and the count is always 0.
var queryable = _database.GetCollection<MyObject>("myname").AsQueryable();
var guid = new Guid("410f9fa9-83d9-4fbf-8ae7-4d309e3eac90");
var count = queryable.Where(x => x.Guid == guid).Count();
The reason is that Linq generates the following request
count: "member_variables", query: { panelid: "410f9fa9-83d9-4fbf-8ae7-4d309e3eac90" }
but the request should be
count: "member_variables", query: { panelid: new BinData(3, "qZ8PQdmDv0+K500wnj6skA==") }
I tried various Linq expressions, but none worked.
queryable.Where(x => x.Guid.ToString() == guid.ToString())
throws the exception: "Unable to determine the serialization information for the expression: x.Guid.ToString()."
queryable.Where(x => x.Guid == new BsonBinaryData(guid));
throws the exception: "Unsupported where clause: ((BsonBinaryData)x.Guid == UuidLegacy:0x24f7ceb84f06d143b6426e8f01cb7825)."
How can I request the documents?
Note: I need to use IQuerable and can't use Mongodb queries.

Resources