Custom Search Queries with SpringBot
This article will walkthrough how to add custom queries via your serverside
project. This enables the client-side to automatically use the custom query parameters as part of the search keywords within the CRUD tile. For this project, we will be using the Codebots LMS Project. You can follow along with the project by downloading the latest version from the public git page.
Introduction of Query Parameters in SpringBot
SpringBot has built-in query parameters to support dynamic queries, which is useful when queries are modified often and used in different contexts. When using SpringBot, query parameters are formatted in a 2D-array, where the items in each array represent OR
, and the arrays together represent AND
.
For example:
[
[a, b, c],
[d, e]
]
would be parsed as (a OR b OR c) AND (d OR e)
.
This query construction allows for complex queries without any extra work required.
By default, this feature can be turned on via the Searchable
property of your attributes in the Entity Diagram.
While the default functionality is powerful, there may be occasions where you want to add query logic and keywords specific to your application domain.
In SpringBot, the dynamic queries are implemented with QueryDSL.
At its core, whenever a query parameter is sent to the server, every nested condition will be transformed into an instance of the Where
class. This can be located at serverside/src/main/java/lmsspring/graphql/utils/Where.java
. This class is the data structure used to pass this information around the applicaiton for later usage.
Now let’s add a new custom query inside our Codebots LMS project.
Create Custom Search Queries
Each course has a corresponding course category. Lets add a custom query to search the courses by the course category names.
Create Custom Query Keyword
- Open
CourseService
underserverside/src/main/java/lmsspring/services
. - Locate the fuction
protected Predicate processCondition(Where condition)
. This function changes the searching parameters intoPredicate
inQueryDSL
toWhere
conditions. The 2D array will then be parsed to aPredicate
, which is used by the QueryDSLExecutor at theRepository
layer. -
Find the protected region
Add any additional cases for the custom query parameters here
and turn it on by replacingoff begin
toon begin
. Insert the following code:case "name": // Use Not equal when where has not equal operation if (condition.getOperation().equals(QueryOperation.notEqual)) { predicate = entity.courseCategory.name.containsIgnoreCase(condition.getValue()).not(); // Otherwise search with contain } else { predicate = entity.courseCategory.name.containsIgnoreCase(condition.getValue()); } break;
Here we are using QueryDSL to generate conditions for courses whose coures category's name contains a certain word
and courses whose coures category's name does not contain a certain word
. The code creates the predicates based on the keyword, operation, and value.
Add new search keyword to the client
Now we need to add the new keyword in the client-side.
- Open
course.model.ts
located atclientside/src/app/models/course
. -
Locate the protected region
Add any additional searchable field names here
and turn it on by replacingoff begin
withon begin
. Insert the following code:'courseCategory'
-
Your file should now look like:
static searchFields: string[] = [ // % protected region % [Add any additional searchable field names here] on begin 'courseCategory' // % protected region % [Add any additional searchable field names here] end ];
Validate the Result
- Restart the client-side and server-side, and go to the URL
http://localhost:4200/course-crud
- After logging in, you can now see the page for the course.
- Create multiple courses, and set the category of one of them.
Now, use the search box.
If you search category
, the client-side will fetch all courses with a course category name containing category
.
Testing with GraphQL Requests
Testing with graphiQL
You also test the new searching function with a GraphQL request.
- Navigate to
http://localhost:8080/graphiql
-
Paste the following content to the Query section:
query GetWithQuery($pageIndex: Int, $pageSize: Int, $orderBy: [OrderBy!], $where: [[Where!]!]) { courses: courses(pageIndex: $pageIndex, pageSize: $pageSize, orderBy: $orderBy, where: $where) { ...CourseProperties courseCatgory { name colour summary __typename } __typename } totalCount: countCourses(where: $where), } fragment CourseProperties on Course { ...CourseBaseProperties name summary coverImage difficulty __typename } fragment CourseBaseProperties on Course { id created modified __typename }
-
Add the following content to the Variables section:
{ "pageIndex":0, "pageSize":10, "orderBy":[ { "path":"created", "descending":true } ], "where":[ [ { "path":"courseCategoryName", "operation":"contains", "value":"category" } ] ] }
If you change the
operation
fromcontains
tonotEqual
you will get the opposite results."operation":"notEqual"
- Run the request and you will receive a response with filtered courses from the server side.
Solution
Have a look at the custom-search-query branch to see the code solution.
Next Steps
See Custom Search Predicates with SpringBot and QueryDSL for more detail on creating custom search predicates.
Was this article helpful?