Java QueryDsl for "update myTable where myColumn in ('interesting', 'values')"? - java

I'm trying to translate this query in QueryDsl:
update myThings set firstColumn = 'newValue' where secondColumn in ('interesting', 'stuff')
I spent hours looking for documentation but the java fu is just not strong enough in this one... :( I can find all kinds of QueryDsl example, but I cant find any for this. I will probably need SimpleExpression.eqAny(CollectionExpression), but I can't figure out how to build such a CollectionExpression around my simple list of strings.
List<String> interestingValues = Arrays.asList("interesting", "stuff");
queryFactory.update(myThings)
.set(myThings.firstColumn, "newValue")
// .where(myThings.secondColumn.in(interestingValues)
// 'in' will probably try to look in table "interestingValues"?
// .where(myThings.secondColumn.eqAny(interestingValues)
// 'eqAny' seems interesting, but doesn't accept a list
.execute();
All I can find is API definitions, but then I get lost in generics any other "new" java concepts which I still have trouble understanding. An example would be very much appreciated.

You have to use new JPAUpdateClause(session, myThings):
JPAUpdateClause<myThings> update = new JPAUpdateClause(session, myThings);
update.set(myThings.firstColumn, "newValue")
.where(myThings.secondColumn.in(interestingValues))
.execute();
If you are using hibernate, use HibernateUpdateClause() instead;

Related

is there way to use multiprefix using elasticsearch java api?

using QueryBuilders.prefixQuery i'm trying to get the list of book title that starts with "L" or "J" is there any way to achieve that?
I know that QueryBuilders.prefixQuery can accept only string like boolQueryBuilder.must(QueryBuilders.prefixQuery("bookTitle", "L")); is there any othere simple way to achieve that?
you can use the boolean clause should and combine two prefix query one for L and one for J which will provide your expected search results, means books with starts from either L or J.
In java code it will look below:
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
PrefixQueryBuilder lPrefixQueryBuilder = new PrefixQueryBuilder("title","L");
PrefixQueryBuilder jPrefixQueryBuilder = new PrefixQueryBuilder("title","J");
boolQueryBuilder.should(lPrefixQueryBuilder);
boolQueryBuilder.should(jPrefixQueryBuilder);

Finding a list of related objects by ID

Let's say for example I have a bridge table called PersonAnimal. I want to search for all the people who have a given animal's ID. The query so far looks like:
Animal animal = getById(Animal.class, animalId)
ObjectSelect
.query(PersonAnimal.class)
.where(PersonAnimal.ANIMAL.eq(animal))
.select(context)
However the first line in the above code segment shows that I first have to retrieve the related object from the database. I want to get rid of that database lookup and instead do something like:
ObjectSelect
.query(PersonAnimal.class)
.where(PersonAnimal.ANIMAL_ID.eq(animalId)) // <- Find by ID instead
.select(context)
Is that possible?
I am running version 4.1 of the Apache Cayenne ORM.
Just as I posted the question I found the answer. You need to create an Expression using a Property object like so:
val findByIdExpr = Property.create(PersonAnimal.ANIMAL.name, Long::class.java).eq(yourId)
val gotList = ObjectSelect
.query(PersonAnimal.class)
.where(findByIdExpr)
.select(context)
Above code is in Kotlin but is also easy to understand from a Java perspective.

Set up Accumulo table through api

new to Accumulo, and this may sound silly, but I was wondering how to setup a table through the api? The documentation is definitely lacking. I have been able to find
conn.tableOperations().createTable("myTable");
as well as like setting up locality groups:
HashSet<Text> metadataColumns = new HashSet<Text>();
metadataColumns.add(new Text("domain"));
metadataColumns.add(new Text("link"));
HashSet<Text> contentColumns = new HashSet<Text>();
contentColumns.add(new Text("body"));
contentColumns.add(new Text("images"));
localityGroups.put("metadata", metadataColumns);
localityGroups.put("content", contentColumns);
conn.tableOperations().setLocalityGroups("mytable", localityGroups);
Map<String, Set<Text>> groups =
conn.tableOperations().getLocalityGroups("mytable");
From the documentation, but I want to know how to take the first approach and build the table. Then build the columns.
Thanks in advance!
There is no inherent schema for a table to set up. Once it is created using the API you found, you can insert whatever key-value pairs you wish in it.

ElasticSearch - Using FilterBuilders

I am new to ElasticSearch and Couchbase. I am building a sample Java application to learn more about ElasticSearch and Couchbase.
Reading the ElasticSearch Java API, Filters are better used in cases where sort on score is not necessary and for caching.
I still haven't figured out how to use FilterBuilders and have following questions:
Can FilterBuilders be used alone to search?
Or Do they always have to be used with a Query? ( If true, can someone please list an example? )
Going through a documentation, if I want to perform a search based on field values and want to use FilterBuilders, how can I accomplish that? (using AndFilterBuilder or TermFilterBuilder or InFilterBuilder? I am not clear about the differences between them.)
For the 3rd question, I actually tested it with search using queries and using filters as shown below.
I got empty result (no rows) when I tried search using FilterBuilders. I am not sure what am I doing wrong.
Any examples will be helpful. I have had a tough time going through documentation which I found sparse and even searching led to various unreliable user forums.
private void processQuery() {
SearchRequestBuilder srb = getSearchRequestBuilder(BUCKET);
QueryBuilder qb = QueryBuilders.fieldQuery("doc.address.state", "TX");
srb.setQuery(qb);
SearchResponse resp = srb.execute().actionGet();
System.out.println("response :" + resp);
}
private void searchWithFilters(){
SearchRequestBuilder srb = getSearchRequestBuilder(BUCKET);
srb.setFilter(FilterBuilders.termFilter("doc.address.state", "tx"));
//AndFilterBuilder andFb = FilterBuilders.andFilter();
//andFb.add(FilterBuilders.termFilter("doc.address.state", "TX"));
//srb.setFilter(andFb);
SearchResponse resp = srb.execute().actionGet();
System.out.println("response :" + resp);
}
--UPDATE--
As suggested in the answer, changing to lowercase "tx" works. With this question resolved. I still have following questions:
In what scenario(s), are filters used with query? What purpose will this serve?
Difference between InFilter, TermFilter and MatchAllFilter. Any illustration will help.
Right, you should use filters to exclude documents from being even considered when executing the query. Filters are faster since they don't involve any scoring, and cacheable as well.
That said, it's pretty obvious that you have to use a filter with the search api, which does execute a query and accepts an optional filter. If you only have a filter you can just use the match_all query together with your filter. A filter can be a simple one, or a compund one in order to combine multiple filters together.
Regarding the Java API, the names used are the names of the filters available, no big difference. Have a look at this search example for instance. In your code I don't see where you do setFilter on your SearchRequestBuilder object. You don't seem to need the and filter either, since you are using a single filter. Furthermore, it might be that you are indexing using the default mappings, thus the term "TX" is lowercased. That's why when you search using the term filter you don't find any match. Try searching for "tx" lowercased.
You can either change your mapping if you want to keep the "TX" term as it is while indexing, probably setting the field as not_analyzed if it should only be a single token. Otherwise you can change filter, you might want to have a look at a query that is analyzed, so that your query wil be analyzed the same way the content was indexed.
Have a look at the query DSL documentation for more information regarding queries and filters:
MatchAllFilter: matches all your document, not that useful I'd say
TermFilter: Filters documents that have fields that contain a term (not analyzed)
AndFilter: compound filter used to put in and two or more filters
Don't know what you mean by InFilterBuilder, couldn't find any filter with this name.
The query usually contains what the user types in through the text search box. Filters are more way to refine the search, for example clicking on facet entries. That's why you would still have the query plus one or more filters.
To append to what #javanna said:
A lot of confusion can come from the fact that filters can be defined in several ways:
standalone (with a required query, for instance match_all if all you need is the filters) (http://www.elasticsearch.org/guide/reference/api/search/filter/)
or as part of a filtered query (http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query/)
What's the difference you might ask. And indeed you can construct exactly the same logic in both ways.
The difference is that a query operates on BOTH the resultset as well as any facets you have defined. Whereas, a Filter (when defined standalone) only operates on the resultset and NOT on any facets you may have defined (explained here: http://www.elasticsearch.org/guide/reference/api/search/filter/)
To add to the other answers, InFilter is only used with FilterBuilders. The definition is, InFilter: A filter for a field based on several terms matching on any of them.
The query Java API uses FilterBuilders, which is a factory for filter builders that can dynamically create a query from Java code. We do this using a form and we build our query based on user selections from it with checkboxes, options, and dropdowns.
Here is some Example code for FilterBuilders and there is a snippet from that link that uses InFilter as shown below:
FilterBuilder filterBuilder;
User user = (User) auth.getPrincipal();
if (user.getGroups() != null && !user.getGroups().isEmpty()) {
filterBuilder = FilterBuilders.boolFilter()
.should(FilterBuilders.nestedFilter("userRoles", FilterBuilders.termFilter("userRoles.key", auth.getName())))
.should(FilterBuilders.nestedFilter("groupRoles", FilterBuilders.inFilter("groupRoles.key", user.getGroups().toArray())));
} else {
filterBuilder = FilterBuilders.nestedFilter("userRoles", FilterBuilders.termFilter("userRoles.key", auth.getName()));
}
...

Querydsl need to query where integer column is less than value

I am having trouble writing a JPAQuery that will execute a simple less than or equal to comparison on an integer column. I have QCommand generated querydsl object which I am trying to use with a JPAquery to execute this very simple query. The query I want to execute would look like this using SQL:
select * from command where retry_count <= 10;
The generated QCommand object defines the retryCount parameter as:
public final SimplePath<Integer> retryCount = createSimple("retryCount", Integer.class);
I have noticed that because it is a SimplePath, when I try to write the JPAQuery, the retryCount variable does not have comparison operators like loe or goe. That column/variable only allows me to do a isNull, isNotNull, eq, and other very simple operators, but no comparison operators. This would look like below, however, obviously not execute the comparison I want, but it works without error:
JPAQuery query = new JPAQuery(entityManager);
query.from(command).where(command.retryCount.isNotNull()).list(command);
In looking around I saw there is a way to create a NumberPath, which seems to be what I want, however, when I attempt the below code I get an exception "java.lang.IllegalArgumentException: Undeclared path 'retryCount'. Add this path as a source to the query to be able to reference it."
JPAQuery query = new JPAQuery(entityManager);
NumberPath<Integer> retryCount = new NumberPath<Integer>(Integer.class, "retryCount");
return query.from(command).where(retryCount.loe(10)).list(command);
So, how can I "add" this path to the source. I have looked around and I cannot find an example that does this nor an explanation as to how this is supposed to be done. The javadocs are not very helpful in this situation. I had been moving along nicely with querydsl, but this is the first roadblock and I'm stumped on writing one of the most simple queries. Any assistance or advice would be greatly appreciated.
The query with manual paths works like this
JPAQuery query = new JPAQuery(entityManager);
NumberPath<Integer> retryCount = new NumberPath<Integer>(Integer.class, command, "retryCount");
return query.from(command).where(retryCount.loe(10)).list(command);
The difference is that you create the retryCount path as a top level path, where as it should be created as a property path with a parent.
How does the Command class look like? There might be some issues in the code generation.

Categories

Resources