Elasticsearch, Nested "ANDS" and "ORS" - java

I am having some difficulty structuring the exact Elasticsearch query that I am looking for, specifically using the java api.
It seems like if I construct a fieldsearch using the java api, I can only use a single field and a single term. If I use a querystring, it looks like I can apply an entire query to a set of fields. What I want to do is apply a specific query to one field, and another query to a different field.
This is confusing I know. This is the type of query I would like to construct
(name contains "foo" or name contains "bar") AND ( date equals today)
I am really loving Elasticsearch for it's speed and flexibility, but the docs on http://www.elasticsearch.org/ are kind of tough to parse (I noticed "introduction" and "concepts" have no links, but the API section does) If anyone has some good resources on mastering these queries, I'd love to see them. Thanks!

Sounds like a bool query with 2 must clause:
matchQuery("name", "foo bar")
rangeQuery("date").from("2013-02-05").to("2013-02-06")
Does it help?

Related

Is it possible to create a QueryDSL Predicate with a String of raw SQL?

I have a Java, GraphQL, Hibernate, PostgreSQL, QueryDSL application that queries a very large PostgreSQL table with over 275 columns.
I've created a GraphQL schema with the 25 most popular columns as query-able fields. I'd like to add a generic "field" input type that consists of a name (the db column name + "_" + operation (like gte, gt, contains, etc.) and a value (the value the user is searching for).
So when the user (in GraphiQL) enters something like (field:{name:"age_gt", value:"50"}) as a search input to the GraphQL query, I can come up with: "age > 50".
All that works fine, but when it's time to create the Predicate and add it to the whole query ( booleanBuilder.and(new Predicate) ), I cannot figure out how to create a Predicate that just contains a raw String of SQL ("age > 50").
I've created several Predicates the "right" way using my entity POJO tied to Hibernate and the jpa generated "Q" object. But I need the ability to add one or more Predicates that are just a String of SQL. I'm not even sure if the ability exists, the documentation for QueryDSL Predicates is non-existent.
I'm thinking PredicateOperation() might be the answer, but again, no documentation and I cannot find any examples online.
My apologies for not posting code, all my stuff is behind a firewall on a different network so there's no cut and paste to my internet machine.
In Hibernate its possible to inject arbitrary SQL using custom functions or the FUNCTION-function (introduced in JPA 2.1). In QueryDSL its possible to inject arbitrary JPQL/HQL through TemplateExpressions. Combined you get:
Expressions.numberTemplate("FUNCTION('SUM', {0}), x)
However, age > 50 as expression is probably valid JPQL as well, so one can just write:
Expressions.numberTemplate("SUM(age)")
Either way, its probably best to create a visitor that traverses the GraphQL query and creates the proper expression in QueryDSL, as TemplateExpressions are prone to SQL injection.

How to query for several, specific fields

So I am exploring how to query mongo from java, and I found several different ways of querying this, and I'm not sure if I'm missing some nuance, thus not fully understanding the queries, or they are the same.
So far I found, for java driver v3.2, this:
collection.find().projection(fields(include("x", "y"), excludeId()))
And I've been told this should work:
BasicDBobject query = new BasicDBObject("x", x).append("y", y);//This example may not compile, I haven't tried it, I'm more talking about the idea and concept.
This query would go with a find(), findOne(), distinct(), and so on.
String fields = "averageSpeed";
coll = db.getCollection(strMongoCollection);
coll.find(fields, query));
So, are both right approaches? Or its purpose is deferent
You always have the option of using the old unwieldy Bson objects yourself, but for the 3.2 driver I'd rather go with the Filters and Projections helper classes.
Thus, a simple search with some criteria can be sent as
collection.find(Filters.eq("myfield", "myvalue"))
For selecting certain fields only, you append a projection:
collection.find(Filters.eq("myfield", "myvalue"))
.projection(Projections.include("myfield", "anotherfield"))
Apart from the more elegant code of the new API, the queries do the same as the BasicDBObject-based calls.

Elasticsearch Java API - fuzzy search with max_expansion

How can I translate the "more complex" fuzzy example from the QueryDSL guide into Java?
What I have so far is this: (Which works fine, but for example I'm unable to find the builder methods for "max_expansion", which would allow me to restrict the query)
QueryBuilders.fuzzyQuery("name", "kimchy")
Any pointers into the right direction are appreciated.
It supposed to be QueryBuilders.fuzzyQuery("name", "kimchy").maxExpansion(5). But, unfortunately, the maxExpansion() method is currently missing. So, until this pull request is merged, the only way to send this query is by expressing it directly in json. You can do it using XContentBuilder.
Construct a Lucene FuzzyQuery directly, then you can pass that option into a constructor arg.

Hibernate and how to avoid name change of modals

I am using Hibernate for a few years but am not sure about the usage of Query and Criteria.
I understood, that one of Hibernate strengths are to control the field name in one place.
If I have the following code:
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list();
What if I change "name" of the Cat in the java object?
Even when using refactor replace (like in Elipse) it will not detect the element as something that needs to be changed!
If so , how do you maintain the field names in Java?
I believe type safe queries are not supported in Hibernate specific api. JPA 2 however has support for it. Read this: Dynamic, typesafe queries in JPA 2.0
I've got the same problem in the past, and actually there's no way to have a typed and refactor resistant(change name) reference of a field in java, so is neither possible have a query builder that allow this, but i tried to build a implementation of a query builder that using some workaround try to allow you to write type safe and refactor resistant query, it's name is ObjectQuery and you can found some information about here.
let me know if it solve your use case !
obviously is nothing of standard so if you are looking to something of standard, is better JPA Typesafe but it not have the same power!

How to search across multiple fields in Lucene using Query Syntax?

I'm searching a lucene index and I'm building search queries like
field1:"hello" AND field2:"world"
but I'd like to search for a value in any field as well as the values in specific fields in the same query i.e.
field1:"hello" AND anyField:"world"
Can anyone tell me how I can search across all indexed fields in this way?
Based on the answers I got for this question: Impact of repeat value across multiple fields in Lucene...
I can put the same search term into multiple fields and therefore create an "all" field which I put everything in. This way I can create a query like...
field1:"hello" AND all:"world"
This seems to work very nicely, prevents the need for huge search queries, and apparently the performance impact is minimal.
Boolean (OR) queries with a clause for each field are used to search multiple fields. The MultiFieldQueryParser will do that as well, but the fields still need to be enumerated. There's no implicit "all" fields; but IndexReader.getFieldNames can acquire them.
This might not apply to you, but in Azure Search, which is based on Lucene, using Lucene syntax, I use this:
name:plywood^100 OR plywood
Results with "plywood" in the "name" field are boosted.

Categories