How to write dynamic sql in Spring Data Azure Cosmos DB - spring-data

We are planning to use Spring Data Azure Cosmos DB v3. I see that we extend CosmosRepository interface and implement our repo and apply #Query annotation
#Query(value = "select * from c where c.firstName = #firstName and c.lastName = #lastName")
List<User> getUsersByTitleAndValue(#Param("firstName") int firstName, #Param("lastName") String lastName);
But we have a need to generate the sql used in #Query dynamically
E.g
String sql = "Select * from some table t"
if(someCondition){
sql.append(" where t.name="+ nameVar);
}
How to achieve this in Spring Data Azure Cosmos DB v3 ?

you can do something like this:-
#Query(value = "select * from c where (#firstName=null or c.firstName=#firstName) and (#lastName=null or c.lastName=#lastName)")
List<User> getUsersByFirstNameAndLastName(#Param("firstName") String firstName, #Param("lastName") String lastName);
This way it will ignore null parameters.

Spring Data Azure Cosmos DB exposes Azure Cosmos DB SQL API through the standard interface of the Spring Data framework. Spring Data framework is not oriented toward dynamic queries, in the sense that there is not a direct way to execute an arbitrary query string against the underlying datastore while staying within Spring Data's conventions. These sources suggest two ways to build dynamic queries programmatically or to define them as mappings:
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
http://shazsterblog.blogspot.com/2017/01/spring-data-jpa-with-dynamic-where.html
Alternatively - Spring Data Azure Cosmos DB is built on top of Azure Cosmos DB Java SDK for SQL API, which is our native Java SDK:
https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-sdk-java-v4
You can pull in a Java bean for our native SDK and use the native SDK for your dynamic queries.

Related

Add SQL string into EF Core LINQ ( append ZQL query)

I have the ASP.Core .Net 5.0 app. I work with PostgreSQL with using of Entity Framework Core. Query to database do with LINQ. How can I add part of raw SQL string to LINQ query?
For example:
var result = Customers.Where(x => x.Age >= 18).Where("==> 'Vasya, Ilya'");
where Customers is repository.
This is necessary because I want to use full text search with ZomboDb.

Spring Data Jpa #query behaviours

Can anybody please tell me #Query annotation will support DB independence query mechanism
Example:
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
}
if i write this query will it support all the DBs like Mysql,oracle, postgres.
i found something like this in spring data jpa reference document site that
#Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
here is this means if i write nativeQuery=true it will treat as native query and if don't writer it will behave like a spring data jpa specific query or how it will behave please clarify.
If you set the nativeQuery flag to true, the query is treated as native sql whose behaviour will depend on DB host.If you dont set nativeQuery=true, then it is treated as JPQL and the real query for DB is generated by JPA according to the DB host hence it is DB independent.

How to execute scalar query on an IMobileServiceSyncTable?

I'm moving my app over from Sqlite-Net to Azure Mobile Services and I'm adding offline sync capabilities.
I'm unsure how to execute arbitrary queries. This is what I have for Sqlite-Net:
var newestDate = await this.connection.ExecuteScalarAsync<DateTime> ("SELECT MAX(TimeStamp) FROM SupplyData");
How can I run this query against my IMobileServiceSyncTable instance?
There is a CreateQuery() method but it does not take any parameters.
Is there any reason you can't use LINQ?
// This query filters out completed TodoItems and items without a timestamp.
List<TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.ToListAsync();
Reference: https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-how-to-use-client-library/#filtering
The alternate to this is to call a custom API. In ASP.NET backends, this is just a WebAPI that uses the underlying Entity Framework stuff. See https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-backend-how-to-use-server-sdk/#how-to-define-a-custom-api-controller For Node.js backends (or Easy Tables / Easy API), see the following sample code: https://github.com/Azure/azure-mobile-apps-node/tree/master/samples/custom-api-sql-stmt

Writing custom n1ql queries in spring

I'm trying to query a spring-data couchbase repository using N1QL queries. I have two doubts:
I'm using #Query annotation to generate queries, my code looks like this:
#Query("#{#n1ql.selectEntity} WHERE $0 = $1 AND #{#n1ql.filter}")
public Page<GsJsonStore> matchJson(String term, String value, Pageable pageable);
//Query
Page<GsJsonStore> p = repo.matchJson("_object.details.status", "ready", pg);
This query doesn't return any results. However, when I run the same query (below) in cbq I get the desired result:
select * from default where _object.details.status = 'ready';
How can I view the query string generated by the Couchbase repository? I'm using spring-boot. Am I correct in using the #Query annotation for this use-case?
Also, how can I perform n1QL queries on CouchbaseOperations template? I know that there's a findByN1QL method, but I didn't find any good documentation about it. Could someone please explain how to use this?
The query looks ok. You did persist your GsJsonStore entities using the Spring Data Couchbase repository did you?
In order to log all the queries generated and executed by the framework (including inline queries like in your case), you can configure the logger like so in a logback.xml configuration:
<logger name="org.springframework.data.couchbase.repository.query" level="debug"/>
You'll see that the query that got executed and the query that you ran in cbq are not the same, since at least you didn't use a WHERE clause.
In CouchbaseOperations there are two methods relative to N1QL queries:
findByN1QL: this expects specific structure of the query, in order to make sure all data necessary to correct deserialization of a Spring Data annotated entity is selected (which is the purpose of the #n1ql.selectEntity and #n1ql.filter SpEL).
findByN1QLProjection is more free-form. If Jackson can deserialize the results of the provided query to the requested Class, then it will. As such, the SELECT clause is much less implicitly restricted in this method.
To use both, you must pass in a N1qlQuery object from the SDK. Such queries can be constructed using factory methods of the N1qlQuery class, for example:
//a version of the query that is constructed from positional parameters
N1qlQuery queryWithParameter = N1qlQuery.parameterized("SELECT name FROM `beer-sample` WHERE name LIKE $0", JsonArray.from("%dog%"));
//let Spring Data execute the query, projecting to the String class
List<String> beerNamesContainingDog = template.findByN1QLProjection(queryWithParameter, String.class);

How to use user defined aggregate in EF 6.1?

I have EF database first project and I would like to build query that will be accessing database using custom aggregate like this below for string concatenation
http://angusmiller.co.za/2010/01/28/clr-user-defined-aggregates-concatenate-strings-with-separator/
Is there any way to do this?