On Tue 2014-02-04 4:24, Martin Braun wrote:
/**
* @return a custom sort object or null
*/
public Sort getSort();
or how to facet, etc...
I want for this stuff to move to annotations (maybe) because I don't really like
the fact that I have to implement an Interface for that (and the current approach
doesn't
allow profiles).
Here is an half formed alternative idea that reverts your model.
class SomeQuery {
// some params as getter / setters
@Query(profile="a", forEntity=Customer.class)
public Query query(QueryBuilder qb) {
return qb.bool()
.must(
qb.keyword()
.onField("name")
.boostedTo(2f)
.matchingParameter("name")
.createQuery();
).createQuery(); //some other boolean query should be here
}
@Sort(profile="a")
Sort getSort() { ... }
...
}
session.createFullTextQuery(someQuery).list();
What this achieved is:
- all query info in one class
- support for multiple profiles
- reuse existing programmatic API
Probably some kind of interface would make more sense to propagate the
return type.
> But annotations in my opinion don't scale very well for tree
structures. Composition, lack of polymorphism are also not easy / elegant in annotations.
> You can see that you had to break the sub queries with string references.
I think they don't scale well in the general case but in this scenario I think
it's ok.
Look at this:
@Queries(@Query(profile = "notName", must = @Must(subQuery =
"someNameForTheQuery")))
@SubQueries(@SubQuery(id = "someNameForTheQuery", query = @Query(must =
@Must(not = true, value = @SearchField(fieldName = "name", propertyName =
"name")))))
I look at it this way: I lose the easy way to do tree structures, but I gain a way to
document my query by having to give names to my sub-queries :).
I can document my subqueries by name using Java local variables :)
Query filterByName =
qb.keyword().onField("name").matchingParameter("name").createQuery();
return qb.all().except(filterByName).createQuery();
BTW, I wonder why in your annotation approach all @Query are junction
queries. There is a small redundancy as the subquery defines a must not
in your example and the top query defines a must. What would happen if
the top query defined a @Should? Bootstrap error?
This is one of the things that throw off Hardy (I think) and me when we
look at the current annotations.
> And I am not sure how you will be able to express other query types that we have
like range, spatial etc. I might be wrong, so it's worth trying. But even then, if we
had one new query type, we
> have to also add an equivalent annotation or add new fields to an existing one.
Uhm. I totally forgot to add this functionality in my rewrite (I have rewritten most of
the code last weekend)
and I implemented a way to pass parameters into QueryTypes. You can even pass parameters
that are dynamically
determined by stating the property to get its value from. With that you can easily do
RangeQueryTypes.
If you want me to elaborate on that, I can provide you with an example.
Yes :)
> What do you mean by query nesting by hand?
Consider you have a query like this (again with boolean syntax):
(queryA || queryD) && (queryB || (queryC) || queryE,...
Now you would have to build a BooleanJunction and several subJunctions
and then put them together. I have written that type of code before and
I made some mistakes because I messed up the variable names in my head.
> And how does the annotation approach differs?
In the annotation Version it would look something like this (example from above):
@Queries(@Query(must = {
@Must(subQuery = "queryAOrQueryD"),
@Must(subQuery = "queryBOrQueryC"),
@Must(subQuery = "queryE")}))
@SubQueries({
@SubQuery(id = "queryAOrQueryD",
query = @Query(should = {@Should(subQuery = "queryA"), @Should(subQuery =
"queryD")})
@SubQuery(id = "queryBOrQueryC",
query = @Query(should = {@Should(subQuery = "queryB"), @Should(subQuery =
"queryC")})
...
//define query[A-E] here.
})
Maybe it's because I don't like to work with the Junctions and put them together
myself,
and maybe it's only me that thinks this would be easier :P.
OK. BTW this is how I would write such query decomposing it. I would not
rely on the intermediary BooleanJunction object.
Query queryA = ...
Query queryB = ...
Query queryC = ...
Query queryD = ...
Query queryE = ...
qb.bool()
.must(
qb.bool().should(queryA).should(queryD).createQuery()
)
.must(
qb.bool().should(queryB).should(queryC).query(E).createQuery()
)
.must(
queryE
)
.createQuery();