jOOQ how to use optional sorting - java

I have a query which selects persons from a table.
SelectConditionStep<PersonRecord> select = context
.selectFrom(Tables.PERSON)
.where(Tables.PERSON.ISDELETED.eq(false));
if(searchValue != null && searchValue.length() > 0){
select.and(Tables.PERSON.LASTNAME.likeIgnoreCase(String.format("%%%s%%", searchValue)));
}
List<PersonRecord> dbPersons = select
.orderBy(Tables.PERSON.LASTNAME, Tables.PERSON.FIRSTNAME, Tables.PERSON.ID)
.limit(length).offset(start)
.fetch();
This code works pretty well. Because I display the data in a datatables table I need to have optional / dynamic sorting capability. I did not find a solution so far.

found the solution myself now:
Collection<SortField<?>> sortFields = new ArrayList<>();
sortFields.add(Tables.PERSON.FIRSTNAME.asc());
List<PersonRecord> dbPersons = select
.orderBy(sortFields)
.limit(length).offset(start)
.fetch();

Related

Offset in pagination of cosmosDb not supported in spring data cosmosdb library

I am trying to get data by pagination from CosmosTemplate.paginationQuery(), but the problem is I am not getting data from the offset that I am setting in pagination object. Below is my code for setting pagination,
DocumentQuery documentQuery = new DocumentQuery(criteriaList, CriteriaType.AND));
if (Objects.nonNull(Offset) && Objects.nonNull(limit)) {
PageRequest cosmosPageRequest = CosmosPageRequest.of(Offset, limit);
documentQuery.with(cosmosPageRequest);
Page<User> page = cosmosTemplate.paginationQuery(documentQuery, User.class, COLLECTION_NAME);
...
}
This always returns me list with first set of objects. So for example when I am setting offset as 11 and limit 10, it is always returning me records with offset 0 to 10. I tried to check library as well but there also no where they are setting offset while retrieving records. Below is the code for the same form azure-cosmosdb library AbstractQueryGenerator.generateCosmosQuery().
protected SqlQuerySpec generateCosmosQuery(#NonNull CosmosQuery query,
#NonNull String queryHead) {
final Pair<String, List<Pair<String, Object>>> queryBody = generateQueryBody(query);
String queryString = String.join(" ", queryHead, queryBody.getFirst(), generateQueryTail(query));
final List<Pair<String, Object>> parameters = queryBody.getSecond();
List<SqlParameter> sqlParameters = parameters.stream()
.map(p -> new SqlParameter("#" + p.getFirst(),
toCosmosDbValue(p.getSecond())))
.collect(Collectors.toList());
if (query.getLimit() > 0) {
queryString = new StringBuilder(queryString)
.append("OFFSET 0 LIMIT ")
.append(query.getLimit()).toString();
}
return new SqlQuerySpec(queryString, sqlParameters);
}
Over here also hard coding for offset is done instead of taking from pagination object. Please can anyone suggest if I am doing anything wrong or getting records based on offset is not supported in this library.
This is a bug in the azure-spring-data-cosmos SDK, where it does not honor the OFFSET as part of CosmosPageRequest and always set it to 0.
It is currently being investigated and will be fixed soon. Follow this issue for updates - https://github.com/Azure/azure-sdk-for-java/issues/28032
However, as a workaround for now, the best way would be to use a custom query using query annotation as mentioned in this example - Usage of offset - https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/repository/integration/ContactRepositoryIT.java#L235
Query annotation - https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/cosmos/azure-spring-data-cosmos-test/src/test/java/com/azure/spring/data/cosmos/repository/repository/ContactRepository.java#L39

Hibernate Search Faceting not working

I´m programming a web application with Java EE, Hibernate Search, JPA and JSF.
I have been reading the hibernate Search documantation over and over again, but I just can´t get faceting to work properly.
I have a database which includes several categorys. I made an example with football clubs.
I have the category Germany, which has the subclases Bundesliga, 2. Bundesliga and so on.
I have also a category called ChampionsLeague, EuroLeague and some other leagues representing different countries.
If I search for "Deutschland" Hibernate Search gives me the correct list of all Football clubs playing in Germany. Some of the football clubs participate in the ChampionsLeague and Euroleage. The Faceting in my left navigation bar gives me the categories in which the german clubs take part in. Also it displays the correct facetedCount.
The problem is, that if I click on one of the categories, Hibernate Search displays me all of the clubs in this category not only the german Clubs, which I have searched for on my initial search.
Can anybody tell me how to fix this problem?
Here is my code:
SearchBean:
public void startKeywordSearch(){
fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Company.class).get();
query = qb
.keyword()
.fuzzy().withEditDistanceUpTo(1).withPrefixLength(0)
.onFields("companyName", "companyShortDescription", "companyLongDescription", "categoryList.categoryName", "and so on")
.matching(keyword)
.createQuery();
categoryNameFacetingRequest = qb.facet()
.name("categoryNameFacet")
.onField("categoryList.categoryName_forFaceting")
.discrete()
.orderedBy(FacetSortOrder.COUNT_DESC)
.includeZeroCounts(false)
.maxFacetCount(100)
.createFacetingRequest();
persistenceQuery = fullTextEntityManager.createFullTextQuery(query, Company.class);
facetManager = fullTextEntityManager.createFullTextQuery(query, Company.class).getFacetManager();
facetManager.enableFaceting(categoryNameFacetingRequest);
result = persistenceQuery.getResultList();
facetResults = facetManager.getFacets("categoryNameFacet");
searchCount = result.size();
Here is my Code for the addFacet Method:
public void addFacet(Facet facet) {
fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
Query luceneQuery = facet.getFacetQuery();
persistenceQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, Company.class);
facetManager.enableFaceting(categoryNameFacetingRequest);
result = persistenceQuery.getResultList();
facetResults = facetManager.getFacets("categoryNameFacet");
FacetSelection facetSelection = facetManager.getFacetGroup("categoryNameFacet");
facetSelection.selectFacets(facet);
result = persistenceQuery.getResultList();
And thats the Code for generating my Link:
<div>
<h:form id="facetForm">
<ul>
<ui:repeat value="#{searchBean.facetResults}" var="facet">
<li><h:commandLink value="#{facet.value}" action="#{searchBean.addFacet(facet)}">
<f:ajax render="#all" />
</h:commandLink> (#{facet.count})</li>
</ui:repeat>
</ul>
</h:form>
</div>
Not sure where exactly you call addFacet, but it looks like you just run the query provided by facet#getFacetQuery. This won't work. The facet query is supposed to be applied on top of the existing query. Either via a boolean query or via a FacetSelection (which acts on top of the original query). The documentation has an example for that:
// create a fulltext query
Query luceneQuery = builder.all().createQuery(); // match all query
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, clazz );
// retrieve facet manager and apply faceting request
FacetManager facetManager = fullTextQuery.getFacetManager();
facetManager.enableFaceting( priceFacetingRequest );
// get the list of Cd
List<Cd> cds = fullTextQuery.list();
assertTrue(cds.size() == 10);
// retrieve the faceting results
List<Facet> facets = facetManager.getFacets( "priceFaceting" );
assertTrue(facets.get(0).getCount() == 2)
// apply first facet as additional search criteria
FacetSelection facetSelection = facetManager.getFacetGroup( "priceFaceting" );
facetSelection.selectFacets( facets.get( 0 ) );
// re-execute the query
cds = fullTextQuery.list();
assertTrue(cds.size() == 2);
See http://docs.jboss.org/hibernate/search/5.3/reference/en-US/html_single/#_restricting_query_results

Select with a set of predefined values in JOOQ for PostgreSQL

Does anybody know is it possible to write in JOOQ select with a set of predefined values? I need it for insert if not exists.
For example,
INSERT INTO test
(text)
SELECT '1234567890123456789'
WHERE
NOT EXISTS (
SELECT id FROM test WHERE text = '1234567890123456789'
);
I've found the answer by myself:
List<Param<?>> params = new LinkedList<>();
params.add(DSL.val("1234567890123456789"));
List<Field<?>> fields = new LinkedList<>();
fields.add(TEST.TEXT);
SelectConditionStep<Record1<TEXT>> notExistsSelect = context.select(TEST.TEXT).from(TEST).where(TEST.TEXT.eq("1234567890123456789"));
SelectConditionStep<Record> insertIntoSelect = context.select(params).whereNotExists(notExistsSelect);
context.insertInto(TEST, fields).select(insertIntoSelect).execute();
But it would be great, if we had an ability to do it via InsertQuery. I've not found the way to do it.

How can I retrieve DBObjects that contains a substring of a search-word?

I am using MongoDB with Java Driver (http://tinyurl.com/dyjxz8k). In my application I want it to be possible to give results that contains a substring of the users search-term. The method looks like this:
*searchlabel = the name of a field
*searchTerm = the users searchword
private void dbSearch(String searchlabel, String searchTerm){
if(searchTerm != null && (searchTerm.length() > 0)){
DBCollection coll = db.getCollection("MediaCollection");
BasicDBObject query = new BasicDBObject(searchlabel, searchTerm);
DBCursor cursor = coll.find();
cursor = coll.find(query);
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
//view.showResult(cursor.next());
}
} finally {
cursor.close();
}
}
}
Does anybody have any idea about how I can solve this? Thanks in advance =) And a small additional question: How can I handle the DBObjects according to presentation in (a JLabel in) view?
For text-searching in Mongo, there are two options:
$regex operator - however unless you have a simple prefix regexp, queries won't use an index, and will result in a full scan, which usually is slow
In Mongo 2.4, a new text index has been introduced. A text query will split your query into words, and do an or-search for documents including any of the words. Text indexes also eliminate some stop-words and have simple stemming for some languages (see the docs).
If you are looking for a more advanced full-text search engine, with more powerful tokenising, stemming, autocomplete etc., maybe a better fit would be e.g. ElasticSearch.
I use this method in the mongo console to search with a regular expression in JavaScript:
// My name to search for
var searchWord = "alex";
// Construct a query with a simple /^alex$/i regex
var query = {};
query.animalName = new RegExp("^"+searchWord+"$","i");
// Perform find operation
var lionsNamedAlex = db.lions.find(query);

jOOQ insert query with returning generated keys

I installed jOOQ into eclipse, generated classes for my mySQL, but I still have problems to write also some basic queries.
I tried to compose insert query with returning of generated keys, but compiler throws error
Table: tblCategory
Columns: category_id, parent_id, name, rem, uipos
Result<TblcategoryRecord> result= create.insertInto(Tblcategory.TBLCATEGORY,
Tblcategory.PARENT_ID, Tblcategory.NAME, Tblcategory.REM, Tblcategory.UIPOS)
.values(node.getParentid())
.values(node.getName())
.values(node.getRem())
.values(node.getUipos())
.returning(Tblcategory.CATEGORY_ID)
.fetch();
tried also other differnt ways
how to do it right way?
thanks
charis
The syntax you're using is for inserting multiple records. This is going to insert 4 records, each with one field.
.values(node.getParentid())
.values(node.getName())
.values(node.getRem())
.values(node.getUipos())
But you declared 4 fields, so that's not going to work:
create.insertInto(Tblcategory.TBLCATEGORY,
Tblcategory.PARENT_ID, Tblcategory.NAME, Tblcategory.REM, Tblcategory.UIPOS)
What you probably want to do is this:
Result<TblcategoryRecord> result = create
.insertInto(Tblcategory.TBLCATEGORY,
Tblcategory.PARENT_ID, Tblcategory.NAME, Tblcategory.REM, Tblcategory.UIPOS)
.values(node.getParentid(), node.getName(), node.getRem(), node.getUipos())
.returning(Tblcategory.CATEGORY_ID)
.fetch();
Or alternatively:
Result<TblcategoryRecord> result = create
.insertInto(Tblcategory.TBLCATEGORY)
.set(Tblcategory.PARENT_ID, node.getParentid())
.set(Tblcategory.NAME, node.getName())
.set(Tblcategory.REM, node.getRem())
.set(Tblcategory.UIPOS, node.getUipos())
.returning(Tblcategory.CATEGORY_ID)
.fetch();
Probably, you're even better off by using
TblcategoryRecord result =
// [...]
.fetchOne();
For more details, consider the manual:
http://www.jooq.org/doc/2.6/manual/sql-building/sql-statements/insert-statement/
Or the Javadoc for creating INSERT statements that return values:
http://www.jooq.org/javadoc/latest/org/jooq/InsertReturningStep.html
preffered SOLUTION
try {
TblcategoryRecord record = (TblcategoryRecord) create
.insertInto(Tblcategory.TBLCATEGORY)
.set(Tblcategory.PARENT_ID, node.getParentid())
.set(Tblcategory.NAME, node.getName())
.set(Tblcategory.REM, node.getRem())
.set(Tblcategory.UIPOS, node.getUipos())
.returning(Tblcategory.CATEGORY_ID)
.fetchOne();
node.setId(record.getCategoryId());
} catch (SQLException e1) { }
Try
YoutableRecord result = create
.insertInto(YOURTABLE)
.set(YOURTABLE.PROD_NAME, "VAL")
.returning(YOURTABLE.ID_PR)
.fetchOne();
int id = result.getValue(Products.PRODUCTS.ID_PR);

Categories

Resources