Lucen/Elasticsearch: a query for a filed with multiple values - java

Here is what I would like to do. I have an index with several documents in Elasticsearch. In every document I have two field: deviceField (name of the device) and pressionField (the value of the pression periodically). I want to query in my index the average pression per device. Do you know a way to do it in a single query? Indeed, I do not want to do a kind of loop 'for' in order to the query per deviceName. It will take too much time due to the fact that I have millions of devices.
Thank you for your attention and your help.
S

You have to use metric aggregations. If you want to list all at same query you use subaggregation
{
"aggs" : {
"devices" : {
"terms" : { "field" : "deviceField" },
"aggs" : {
"avg_pression" : { "avg" : { "field" : "pressionField" } }
}
}
}
}
Here is the link of documentation:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html

Related

Elastic ExistsRequst for field value and field type

I'm working on a project creating integration tests and the data I have includes all the schema updates people have done in the past. For example My "documents" field has a property of user, which has been an array in the past, but is now an Object.
I'm trying to write an integration test that will ONLY use a document if the user type is Object, not array.
Is there a way to do this with an ExistsQuery? So far I have not been able to find anything. Here's my current query which brings back inconsistent data:
GET _search
{
"query" : {
"bool" : {
"must" : {
"exists" : {
"document.user"
}
}
}
}
}
Ideally I'd like to check for document.user[] and filter those values out.
You can use script query like below
{
"query": {
"script": {
"script": "if (doc['document.keyword'].size()==1) return true;"
}
}
}

HashMap cannot be cast to model when trying to iterate set

I am using spring data jpa for creating micro services. In repository I am using JPQL query. Using following code I am able to get set of data. But I want to iterate set of data for further logic.
For iteration I used for each but when I am using for each loop I am getting error "java.util.HashMap cannot be cast to com.spacestudy.model.RoomDepartmentMapping",
public Set<RoomDepartmentMapping> loadStatusOfRooms() {
Set<RoomDepartmentMapping> roomDeptMapping = roomDeptMappingRepo.findStaus();
return roomDeptMapping;
}
}
Repository
#Repository
public interface RoomDepartmentMappingRepository extends JpaRepository<RoomDepartmentMapping, Integer> {
#Query("select new map(roomDeptMap.sStatus as sStatus) from RoomDepartmentMapping as roomDeptMap")
Set<RoomDepartmentMapping> findStaus();
}
Result
[
{
"sStatus": "A"
},
{
"sStatus": "I"
},
{
"sStatus": "R"
}
]
Expecting Result
[
{
"sStatus": "Accepted"
},
{
"sStatus": "In Progress"
},
{
"sStatus": "Remaining"
}
]
For getting above expected result I am trying to iterate Set of data using for each and planning to use switch case. But I am not able to iterate using following loop.
For each loop
for(RoomDepartmentMapping roomDeptMappingObj:roomDeptMapping) {
System.out.println(roomDeptMappingObj);
}
Can any one tell me why I am not able to iterate set using for each loop?
Or please suggest any another way to do that.
Based on the name of your method I will assume that you need all available status values.
The query will be:
#Query("select distinct rdm.sStatus from RoomDepartmentMapping rdm")
Set<String> findStatus();
distinct => you need set
Set => RoomDepartmentMapping sStatus is a String

Firebase data retrieval java

{
"Account1" :
{
Push_key(): { Carplate: "ABC1234" }
Push_key(): { Carplate: "ABC" }
Push_key(): { Carplate: "A" }
}
}
This is how the database looks like.
I would like to retrieve the third data which contains "A" alone ONLY.
I am using startAt() and endAt() for data retrieval:
Query query = ref.child("Account1").orderByChild("Carplate").startAt("A").endAt("A"+"\uf8ff");
But it returns all 3 records. (I think its due to they are all started at "A".)
Need help! Please!
You should look at the equalTo() method for this (from the doc):
The equalTo() method allows you to filter based on exact matches. As is the case with the other range queries, it will fire for each matching child node.
To adapt it to your query you might try:
Query query = ref.child("Account1").orderByChild("Carplate").equalTo("A");

MongoDB updating an array element in a specific index using the Java driver

Usually, I avoid asking a new question as I always find a "close-enough" answer to my problem.
But this time I surprisingly have a fundamental and straightforward question - without any lead.
I have a straightforward MongoDB document that holds two arrays:
The 1st containing three numbers (ints) - each represent a code-number of a selected (predefined) question.
The 2nd was holding 3 Strings - that are the answers given by the user to these three correspondent questions.
For example, let's say subject code 12 is - "What's your 1st dog's name?", and the user's answer was: "Spiky", etc...
So I end up with something like:
{
"_id" : ObjectId("..."),
"questionCodesArray" : [
12,
56,
3
],
"answersArray" : [
"Spiky",
"go swimming",
"blabla.."
]
}
Now, I'd like to be able to allow the users to change their mind and choose a different question and supply a different answer to it.
For this, I need to have only the index of my element and access it via this index to change it using update() or findAndModify() [or any other method] and all the answers out there are "key-value style" which is not needed.
In simple Java I would've simply done something like:
questionsCodesArry[index] = newValue; and
answersArray[index] = newAnswerString;
All my attempts to write a descent query to do this simple index-based updating have failed.
Any help will be appreciated.
Thank you.
In plain MongoDB syntax what you need is this:
collection.update({
/*your filter goes here*/
}, {
$set: {
"questionCodesArray.<zero-based-index>": "new value"
}
})
I don't have a Java environment here to translate this into your driver's world. I might be able to do so tonight, though.
Still, I would definitely vote for a different, more natural and less error-prone design where you'd structure your data like so:
{
"_id" : ObjectId("59b635ffad44fad6662d8591"),
"answers" : [
{
"questionCode" : 12,
"answer" : "Spiky"
},
{
"questionCode" : 56,
"answer" : "go swimming"
},
{
"questionCode" : 3,
"answer" : "blabla.."
}
]
}
If that's an option for you I shall happily provide you the right update statement for this layout, too.
Well, after some trials here is a c&p complete and full method to change an array's element by a given index:
public boolean changeArrayValue(DB db, String collectionName, long id, String arrayNameKey, int index, Object newValue)
{
DBCollection collection = db.getCollection(collectionName);
DBObject query = new BasicDBObject("id",id);//unique id is recommended
DBObject update = new BasicDBObject("$set", new BasicDBObject(arrayNameKey+"."+index, newValue));
DBObject result = collection.findAndModify(query, null, null, false, update,true, true);
//Just for precaution
if(result == null)
return false;
return (((BasicDBList)result.get(arrayNameKey)).get(index)).equals(newValue);
}
As you can see the main issue lays in the $set line here: arrayNameKey+"."+index .
In the result I've put the needed flags to get the updated result, which is of type BasicDBList<Object>.
Pleases note that you'll have to add all the needed checks and validations according to your taste.
Enjoy..

Should wild card characters (* and ?) be allowed for fieldMatching in elastic search?

I am getting a response if I search the details using wildCard characters in the elastic search for fieldMatch.Is this as expected?
Field queries are a version of query_string queries, which support using * and ? as wildcards. So, it is expected that the following will return results for "elasticsearch".
{
"field" : { "engine" : "elastic*ch" }
}
{
"field" : { "engine" : "elasticsea?ch" }
}

Categories