I would like to build a query to elasticsearch using search criteria from a html form. I have several input fields on the html page. For example, if the user fill two of these fields I could write :
BoolQueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("archivo", "archivo1"))
.must(QueryBuilders.termQuery("nombre", "documento1"));
But... what if the user fill three fields I could have :
BoolQueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("archivo", "archivo1"))
.must(QueryBuilders.termQuery("nombre", "documento1"))
.must(QueryBuilders.termQuery("third", "test"));
Is there any way to dinamicall build this kind of queries?
BoolQueryBuilder.must() adds a predicate, it does not replace the previous one.
Therefore, suppose that the value of the field archivo is in the variable inputArchivo and so on, you can check if the field is filled then add the predicate :
BoolQueryBuilder query = QueryBuilders.boolQuery();
if(inputArchivo != null && !inputArchivo.isEmpty()) {
query.must(QueryBuilders.termQuery("archivo", inputArchivo));
}
if(inputNombre != null && !inputNombre.isEmpty()) {
query.must(QueryBuilders.termQuery("nombre", inputNombre));
}
if(inputThird != null && !inputThird.isEmpty()) {
query.must(QueryBuilders.termQuery("third", inputThird));
}
and yet if you don't know what terms will came you can iterate over a HashMap with the values:
for (Map.Entry<String, Object> entry : map.entrySet()) {
query.must(QueryBuilders.termQuery(entry.getKey, entry.getValue))
}
Related
I am trying to write a method that returns me IDs (as a List ) of all records from a collection that have a certain status.
I am looking for a solution, but unfortunately I cannot find anything correct.
I currently have something like this:
List<String> getAllLecturersIdList() {
MongoCollection<Document> collection.mongoTemplate.getCollection("lecturers");
MongoCursor<Document> cursor = collection.find().iterator();
ArrayList<String> listOfIDS = new ArrayList<>();
while (cursor.hasNext()) {
listOfIDS.add(cursor.next().getObjectId("_id").toString());
}
return listOfIDS;
}
This method returns me a list of IDs of all lecturers.
The lecturer entity also has a "status" field with values like ACTIVE, LEAVE, FIRED and so on.
I would like to have only IDs of lecturers who have ACTIVE status to be returned to me.
How to do it to have only entities with ACTIVE status when returning from the collection, and not to clean the repository / services level?
Thanks for help in advance!
Important - I don't want an entity structure to be created in the application.
Therefore, the solution cannot contain a POJO / Entity Class and here is the problem (I cannot use e.g. Criteria, because every example is with defined entity )
You can fallback to the low level MongoOperations#executeQuery method if there is no result type mapping your query results:
List<String> getAllLecturersIdList() {
Query query = new Query();
query.fields().include("_id");
query.addCriteria(Criteria.where("status").is("ACTIVE"));
ArrayList<String> listOfIDS = new ArrayList<>();
mongoTemplate.executeQuery(query, "lecturers", document -> listOfIDS.add(document.getObjectId("_id").toString()));
return listOfIDS;
}
The following should work:
List<String> getAllLecturersIdList() {
MongoCollection<Document> collection.mongoTemplate.getCollection("lecturers");
MongoCursor<Document> cursor = collection.find().iterator();
ArrayList<String> listOfIDS = new ArrayList<>();
while (cursor.hasNext()) {
Document document = cursor.next();
if (document.getString("status") == "ACTIVE") {
listOfIDS.add(document.getObjectId("_id").toString());
}
}
return listOfIDS;
}
I am trying to create query for search filter using elasticsearch. I created query that shows results based on search term, price range and brand list. Results shown for searchterm and price range is right but when brand list is provided all results related to selected brand is shown.
I want results for searchterm AND price AND brands
This is my query
BoolQueryBuilder query = QueryBuilders.boolQuery();
for (String key : brands) {
query.must(QueryBuilders.matchQuery("brand", key));
}
SearchResponse searchresponse = client
.prepareSearch("product")
.setTypes("product")
.setQuery(
QueryBuilders.matchPhraseQuery("name", pSearchTerm))
.setPostFilter(
QueryBuilders.rangeQuery("unit_price").from(min)
.to(max))
.setQuery(query).setExplain(true)
.execute().actionGet();
what am i doing wrong here?
You have two setQuery() calls so the second one is overriding the first one. You need to combine all your constraints into one query like this:
// brand list
BoolQueryBuilder query = QueryBuilders.boolQuery();
for (String key : brands) {
query.must(QueryBuilders.matchQuery("brand", key));
}
// search term
query.must(QueryBuilders.matchPhraseQuery("name", pSearchTerm));
// price range
query.filter(QueryBuilders.rangeQuery("unit_price").from(min).to(max));
SearchResponse searchresponse = client
.prepareSearch("product")
.setTypes("product")
.setQuery(query)
.setExplain(true)
.execute().actionGet();
I index objects in Elasticsearch 2.4 where one of the fields is an array of other objects, for example, something like this:
{
A : 1,
B : [{BB : 1},{BB : 2},{BB : 4},{BB : 5}]
}
Is it possible to query Elasticsearch and apply a filter to hide some of the arrays's B values, for example, to hide values where BB is less than 3 such that a result would be
{
A : 1,
B : [{BB : 4},{BB : 5}]
}
P.S.
I'm using Java API
I didn't find a flexible built in way of doing it so I decided to filter manually. Here's my implementation:
SearchResponse resp = request.execute().actionGet();
for (SearchHit hit : resp.getHits().getHits()) {
Map<String, Object> source = hit.getSource();
transformHitSource(source); // a method where you work with a map and can modify it as you want
XContentBuilder xContentBuilder = jsonBuilder().startObject();
for (Map.Entry<String, Object> entry : source.entrySet()) {
xContentBuilder.field(entry.getKey(), entry.getValue());
}
BytesReference bytes = xContentBuilder.endObject().bytes();
((InternalSearchHit) hit).sourceRef(bytes);
}
I trying to perform a query in my mongo database using java code. I want to filter the result of the query using cursor. Basically I want to filter the cursor results two times. My query return some documents, and I want to filter them based on a field of document and a sub-field of the first field. For example:
DBCursor cursor = coll.find(query);
while(cursor.hasNext()) {
BasicDBObject obj = (BasicDBObject) cursor.next();
System.out.println(obj.getString("images"));
}
Return the image field from all quered documents. What should I do if I want to return the field "link" which is a subfield of field "images"? I tried obj.getString("images").getString("link"), however it doesn't work. Images is an array with three fields the first one is the filed "link". When the above return is the following: [ { "link" : "http://distilleryimage1.ak.instagram.com/fc7c5_7.jpg" , "phash" : "01000010101000101010111101" , "persons" : 1}] . I want to return just the first field link.
Just get images as ArrayList:
ArrayList<BasicDBObject> images = (ArrayList<BasicDBObject>)obj.get("images");
for(BasicDBObject image: images)
{
String link = image.getString("link");
.......
}
I have a JSON in MongoDB with the following structure:
{
id:"_234234",
"stationId":"ALM",
"storageData": {
}
}
To retrieve JSON with storageData equal to null, in MongoDB I query as:
db.collection.find({"storageData":{"$gt" : {}}})
It gives me list of JSON bodies with empty storageData. So how do I represent that in Java
BasicDBObject obj=new BasicDDBObject("storageData", new BasicDBObject("$gt",{}));
collection.find(obj);
I am getting an error near BasicDBObject("$gt",{}))...
How do I represent ("$gt",{}) in Java??
First understand that null is a valid value. This would be valid:
{
id:"_234234",
StationId:"ALM",
StorageData: null
}
and retrieving the document, asking for storagedata which is null would retrieve the doc with the id _234234.
If what you need is to check which documents DON'T have the key "storagedata" then use the $exist keyword or construct the query in this way:
db.yourcollection.find("this.storagedata == null")
I would do it via query, and not in Java because it would alleviate cpu time and memory.
All you want to to here is represent an empty object:
BasicDBObject query = new BasicDBObject(
"storageData", new BasicDBObject(
"$gt",new BasicDBObject()
)
);
Which of course produces the query:
{ "storageData" : { "$gt" : { } } }
So that's it, just call BasicDBObject without any arguments.