I am stuck trying to get a query (QueryDSL) to work that gives me a count of distinct categories.
For example, what I am trying to achieve:
categoryA -> 10 entries
categoryB -> 20 entries
This is what i have so far:
query().from(application)
.transform(groupBy(application.category).as(list(application)));
However, this gives me for each category a list of all whole entries, I just want to get a count of this.
I tried messing around with count() but no luck.
Anybody know how to do this?
Note that as of Querydsl 4.x, the accepted answer by Timo Westkämper is no longer valid. Breaking changes in Querydsl 4.0 have removed the query.list() method.
A solution working with Querydsl 4.0+ would now be:
query.from(application)
.groupBy(application.category)
.select(application.category, application.category.count())
.fetch();
transform combined groupBy is meant to construct tree structures out of flat result sets. What you need can be easier expressed as
query.from(application)
.groupBy(application.category)
.list(application.category, application.category.count())
If using 4.1.4, you may need to use a JPAQueryFactory instead of JPAQuery
If using JPAQuery, there is no select() or fetch() on the return from groupBy.
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
queryFactory
.select(application.category, application.category.count())
.from(application)
.groupBy(application.category)
.fetch();
In QueryDSL 4.4.0:
query.from(application)
.groupBy(application.category)
.transform(GroupBy.groupBy(application.category)).as(application.category.count()))
Learn more on: https://www.tabnine.com/code/java/methods/com.querydsl.jpa.JPQLQuery/transform
Related
Using Jooq, I am trying to fetch from a table by id first, if no matches found, then fetch by handle again.
And I want all fields of the returned rows, not just one.
Field<?> firstMatch = DSL.select(Tables.MY_TABLE.fields())
.from(Tables.MY_TABLE.fields())
.where(Tables.MY_TABLE.ID.eq(id))
.asfield(); // This is wrong, because it supports only one field, but above we selected Tables.MY_TABLE.fields(), which is plural.
Field<?> secondMatch = DSL.select(Tables.MY_TABLE.fields())
.from(Tables.MY_TABLE.fields())
.where(Tables.MY_TABLE.HANDLE.eq(handle))
.asfield(); // Same as above.
dslContext.select(DSL.coalesce(firstMatch, secondMatch))
.fetchInto(MyClass.class);
Due to the mistake mentioned above in the code, the following error occurs:
Can only use single-column ResultProviderQuery as a field
I am wondering how to make firstMatch and secondMatch two lists of fields, instead of two fields?
I tried
Field<?>[] secondMatch = DSL.select(Tables.MY_TABLE.fields())
.from(Tables.MY_TABLE.fields())
.where(Tables.MY_TABLE.HANDLE.eq(handle))
.fields();
but the following error occurred in the line containing DSL.coalesce
Type interface org.jooq.Field is not supported in dialect DEFAULT
Thanks in advance!
This sounds much more like something you'd do with a simple OR?
dslContext.selectFrom(MY_TABLE)
.where(MY_TABLE.ID.eq(id))
// The ne(id) part might not be required...
.or(MY_TABLE.ID.ne(id).and(MY_TABLE.HANDLE.eq(handle))
.fetchInto(MyClass.class);
If the two result sets should be completely exclusive, then you can do this:
dslContext.selectFrom(MY_TABLE)
.where(MY_TABLE.ID.eq(id))
.or(MY_TABLE.HANDLE.eq(handle).and(notExists(
selectFrom(MY_TABLE).where(MY_TABLE.ID.eq(id))
)))
.fetchInto(MyClass.class);
If on your database product, a query using OR doesn't perform well, you can write an equivalent query with UNION ALL, which might perform better.
I have the SQL like:
select *
from some_table
where (select array(select unnest(first_array_field) except select unnest(second_array_field))) #> '{some_value}';
This is my try to write the where condition for that query in a JOOQ way:
private Condition selectAwayValue(
List<Long> list) {
var allSelect = dslContext
.select(TABLE.ARRAY_1)
.from(DSL.unnest(TABLE.ARRAY_1));
var homeSelect = dslContext
.select(TABLE.ARRAY_2)
.from(DSL.unnest(TABLE.ARRAY_2));
var awaySelect = allSelect.except(homeSelect);
var awayArray = dslContext.select(DSL.array(awaySelect));
return awayArray.asField().contains(awayCompetitorIdsList);
}
I'm facing 2 problems here:
I got the different SQL than I expected (see above)
Also got the exception like Cannot convert from 5 (class java.lang.Long) to class [Ljava.lang.Long;
I understand what's the exceptions says to me, but don't understand why :)
What's would be the best way to write my SQL in a jooq syntax?
I'm using the latest stable jooq version, the latest stable Postgres version
thanks
Alternative solution
If you think of your problem this way:
select *
from some_table
where first_array_field #> '{some_value}'
and not second_array_field #> '{some_value}';
Then, the problem is a lot simpler to express in jOOQ as well
ctx.selectFrom(SOME_TABLE)
.where(SOME_TABLE.FIRST_ARRAY_FIELD.contains(new Long[] { someValue }))
.andNot(SOME_TABLE.SECOND_ARRAY_FIELD.contains(new Long[] { someValue }))
.fetch();
Why your solution didn't work
Of course, you could pull this off using your own approach. Regarding the problems you've observed:
I got the different SQL than I expected (see above)
That syntax where you put UNNEST() in SELECT is not supported by jOOQ. It is quite the weird syntax in PostgreSQL as well, and doesn't do what you might think it does in many ways. Have you tried putting two instances of UNNEST() in SELECT? The second one won't form a cartesian product like the first one. Rows from it will be matched with the first one's rows by ordinality.
However, using UNNEST in FROM is correct and also more intuitive in native PostgreSQL, even if it's a bit longer. And it's supported by jOOQ.
Also got the exception like Cannot convert from 5 (class java.lang.Long) to class [Ljava.lang.Long;
This is because you seem to be calling Field.contains() with a scalar argument, instead of an array. See the example from the Javadoc, or my example above:
// Use this expression
val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
// ... to render this SQL
ARRAY[1, 2, 3] #> ARRAY[1, 2]
But again, I think my alternative approach is much simpler.
Using the Elasticsearch High Level REST Client for Java v7.3
I have a few fields in the schema that look like this:
{
"document_type" : ["Utility", "Credit"]
}
Basically one field could have an array of strings as the value. I not only need to query for a specific document_type, but also a general string query.
I've tried the following code:
QueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.queryStringQuery(terms))
.filter(QueryBuilders.termQuery("document_type", "Utility"));
...which does not return any results. If I remove the ".filter()" part the query returns fine, but the filter appears to prevent any results from coming back. I'm suspecting it's because document_type is a multi-valued array - maybe I'm wrong though. How would I build a query query all documents for specific terms, but also filter by document_type?
I think, the reason is the wrong query. Consider using the terms query instead of term query. There is also a eqivalent in the java api.
Here is a good overview of the query qsl queries and their eqivalent in the high level rest client: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-query-builders.html
The new flexible environment datastore interface does not seem to support IN operation when running a query. I hope that I'm wrong, and if so, how can one use an IN operator in the new Java interface of Datastore?
A query like - WHERE color IN('RED', 'BLACK'), it is not supported by the Datastore (server side). Same is the case with OR operator (e.g. WHERE color='RED' OR color='BLACK'). Some client APIs have added this functionality by splitting the query into multiple and then merging the results from each query. The new google-cloud-java API does not support this yet. For now, you would have to run multiple queries for each value in the IN clause and merge the results.
Here’s an example from the documentation:
If you want to set more than one filter on a query, you must use CompositeFilter, which requires at least two filters.
Filter tooShortFilter = new FilterPredicate("height", FilterOperator.LESS_THAN, minHeight);
Filter tooTallFilter = new FilterPredicate("height", FilterOperator.GREATER_THAN, maxHeight);
Filter heightOutOfRangeFilter = CompositeFilterOperator.or(tooShortFilter, tooTallFilter);
Query q = new Query("Person").setFilter(heightOutOfRangeFilter);
You can also use .and(). The code here is for Java 7. For Java 8 you can find a corresponding code in the documentation referenced above. I hope that helps.
Now to IN. While I have not tried it myself recently, the current documentation states that it can still be used as an operator. According to it, something like the code below should work:
Filter propertyFilter = new FilterPredicate("height", FilterOperator.IN, minHeights);
Query q = new Query("Person").setFilter(propertyFilter);
Alternatively, you could use Google GQL. It will allow you to write SQL-like syntax, in which you can use in(...).
I tried using the repository query methods, but I got an error informing that it is not supported.
Only solved for me using the #Query annotation;
Example:
#Query("select * from UserGroup where name IN #names")
List<Company> findAllByName(List<String> names);
I have a SQL request like:
select X from "myTable" where (cond1 AND cond2) OR (cond3 AND cond 4)...
How many (cond AND cond) can I have in my clause where? Because it makes a stackOverFlow error with my 24578 conditions.
final List update = xService.getCountUpdate(couple);
couple is a list build by that way (every line in my file this is done ):
dcIssn = new ArrayList<String>();
dcIssn.add(0, row.getCell(dc).getStringCellValue());
dcIssn.add(1, row.getCell(issn).getStringCellValue());
couple.add(dcIssn);
I solve my problem.
The problem was not my query, just my StringBuilder which was too short for the query.
Thank you for helping me =)
There is no limit to the number of predicates that can be included in a search condition. For more information about search conditions and predicates.
see this:-
https://technet.microsoft.com/en-us/library/ms189575(v=sql.105).aspx