I need to update an index document for an elasticsearch table and this is the code I have implemented. But it is not working, what's wrong and how should I implement this?
My code.
Map<String, Object> matching_result;
for (SearchHit hit : response_text.getHits()) {
matching_result = hit.getSource();
String flag_value = matching_result.get("flag").toString();
matching_result.put("flag", true);
}
String indexString = JSONConverter.toJsonString(matching_result);
IndexResponse response = client.prepareIndex("index_name", "data").setSource(indexString).execute().actionGet();
boolean created = response.isCreated();
System.out.println("created or updated--------------------->" + created);
System.out.println("flag value==========" + matching_result.get("flag"));
return actual_theme;
(JSONConverter.toJsonString) is our library class for converting to json string.
What is wrong with this query?
Instead of updating the existing document it is creating a new one. I want to change the existing one.
Based on your example code, it looks like by "update" you mean you are trying to replace the entire document. In order to do this, you must specify the id of the document you wish to update.
Using the Java API, in addition to calling setSource on the IndexRequestBuilder, you would also need to supply the id by calling setId. For example:
IndexResponse response = client.prepareIndex("index_name", "data")
.setSource(indexString)
.setId(123) <----- supply the ID of the document you want to replace
.execute()
.actionGet();
Otherwise, just so you know, in ES you have the option to do a partial update. That is, only update certain fields in the document. This can be done with a script or by providing a partial document. Have a look at the documentation for the Update API.
In either case, you need to provide ES with the ID for the document you wish to modify.
Related
I'm trying to update data in Elastic Search in my Java program with TranportClient class. I know I can UPDATE in this way :
XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
.field("source.ivarId", source.ivarId)
.field("source.channel", source.channel)
.field("source.bacId", source.bacId).endObject();
UpdateResponse response = client.prepareUpdate(_index, _type, _id).setDoc(builder.string()).get();
while source is my user-defined class which contains 3 fields : ivarId, channel and bacId.
But I want to know is there any method that could do the same thing, but using another more efficient and easier way, so that I don't need to assign each field inside a class? For example, can I do like this?
XContentBuilder builder = XContentFactory.jsonBuilder().startObject()
.field("source", source).endObject();
UpdateResponse response = client.prepareUpdate(_index, _type, _id).setDoc(builder.string()).get();
I tried the latter method, and I got this exception :
MapperParsingException[object mapping for [source] tried to parse field [source] as object, but found a concrete value]
I'm using Java 1.8.0.121, and both versions of ElasticSearch and TransportClient are 5.1. Thanks!
The answer is much more easier than I thought.
Gson gson = new Gson();
String sourceJsonString = gson.toJson(updateContent);
UpdateResponse response = client
.prepareUpdate(_index, "logs", id).setDoc(sourceJsonString).get();
updateContent is the object that contained new data, just to transform it to Json string, then use that to update, done.
I am totally new to Java 1.8 and to Play Framework.
Just a simple question: from my application I have to call a REST web service thoroug Play framework and then parse the XML response in order to find some elements of interest.
My code, as I found on the guide, looks as follows:
WSRequest request = ws.url("http://example.com").setQueryParameter("paramKey", "paramValue");
CompletionStage<Document> documentPromise = request.get()
.thenApply(WSResponse::asXml);
The question is: how do I parse the "documentPromise" result to find the elements inside the XML?
Thank you
You just have to, instead of use WSResponse::asXml, apply that method yourself and process it as needed. For example, if you just want to return the text of an element, given an id:
// (...)
.thenApply(res -> {
Document doc = res.asXml();
Element e = doc.getElementById("someId");
return ok(e.getTextContent());
});
I'm having some troubles with different back-end processing of POST rest calls. I have two different objects which are updated through two different POST methods in my back-end. I catch the objects as a JsonNode, and in order to parse the attributes which I need to update, i create an iterator like so :
final Iterator<String> fieldNames = attributes.fieldNames();
The problem comes when I send my data from angular, in one case I need to explicitly send it like angular.toJson(data) in order to properly grab all the field names, and in the other case I just send the data (without the angular json conversion). Why is this behavior occurring ? Does this have to do with how I create the $http post call ? Here are the two different calls from angular:
$http.post(URL, angular.toJson(data)).success(function(data){
/*whatever*/ }).error(function(data) {
/*whatever*/ });
//Second call looks like this
var promise = $http({method: 'POST', url:URL, data:data, cache:'false'});
//this one i resolve using $q.all
I truncated the code to just the important stuff. My data is created like this currently(tried multiple ways in order to skip the need for toJson):
var data = "{\"Attribute1:\"+"\""+$scope.value1+"\","+
"\"Attribute2:\"+"\""+$scope.value2+"\"}";
How do I need to send the json data in order for it to correctly be converted to a JsonNode in my back-end, so I can properly iterate the fieldNames ?
I did manage to come to a common solution which consumes the json correctly in my back-end. I declared my json objects in angular like this :
$scope.dataToSend = {
"SomeAttribute" : "",
"SomeOtherAttribute" : ""
};
And then added my values like so :
$scope.dataTosend.SomeAttribute = someValue;
$scope.dataTosend.SomeOtherAttribute = someOtherValue;
No longer need to send the data with angular.toJson().
I'm developing a Java application using MongoDB and Java-driver.
I need to parse a BasicDBObject into an own object of my code, and I don't know if there is a way to develop automatically.
Is it possible to parse from BasicDBObject to JSON String? Then, I could parse from JSON String to my own Object, for example with GSON library. Something like
BasicDBObject object;
String myJSONString = object.toString();
Gson gson = new Gson();
MyOwnObject myObject = gson.fromJson(myJSONString, MyOwnObject.class);
And I don't want to add complex to my code, also I don't to add more extern libraries. I don't want to add Gson library or other.
Any ideas?? Is it possible to do this without external libraries??
Thanks!!
You could have taken a look at the API: Just call object#toString() (http://api.mongodb.org/java/2.0/com/mongodb/BasicDBObject.html#toString()).
You could either use Groovy with gmongo library for that, there you have lots of handy tools for such casting.
If the language change is not an option for you, write your own reflection-based mapper. If you POJO is simple enough, the mapper shall be pretty simple.
This is the correct answer to my question
From http://docs.mongodb.org/ecosystem/tutorial/use-java-dbobject-to-perform-saves/
For example, suppose one had a class called Tweet that they wanted to save:
public class Tweet implements DBObject {
/* ... */
}
Then you can say:
Tweet myTweet = new Tweet();
myTweet.put("user", userId);
myTweet.put("message", msg);
myTweet.put("date", new Date());
collection.insert(myTweet);
When a document is retrieved from the database, it is automatically converted to a DBObject. To convert it to an instance of your class, use DBCollection.setObjectClass():
collection.setObjectClass(Tweet.class);
Tweet myTweet = (Tweet)collection.findOne();
If for some reason you wanted to change the message you can simply take that tweet and save it back after updating the field.
Tweet myTweet = (Tweet)collection.findOne();
myTweet.put("message", newMsg);
collection.save(myTweet);
I have successfully created an index using elasticsearch, and can serialized those exact json payloads back to my java application.
for (SearchHit searchHit : searchResponse.getHits()) {
try {
result.getItems().add(objectMapper.readValue(searchHit.getSourceRef().streamInput(), Program.class));
} catch (IOException e) {
throw new IllegalArgumentException("Cannot marshall json", e);
}
}
The payload size that I export to elasticsearch is very large, but the response, I want to be very small. I also want to allow the client to dynamically include or exclude some fields. So I did this, where fields is an array of fields I want to include. This works well in that only the fields I ask for are returned, however the searchHit.getSourceRef is now null. Is there any way to get it to just copy the fields that I included via Jackson? Or must I always return the entire source object? Or do I have to write some sort of mapping code to translate (I would really like to avoid this) ?
SearchResponse searchResponse = transportClient.prepareSearch("programs")
.addFields(fields.toArray(new String[fields.size()]))
.setTypes("program")
.setQuery(query).setFrom(start).setSize(pageSize)
.execute().actionGet();
however the searchHit.getSourceRef is now null.
It is null because searchHit.getSource() is also null. As far as I know you have to add "_source" to your fields list when you do the search. Something like this:
ArrayList<String> fields = new ArrayList<String>();
fields. add("field1");
fields.add("field2");
fields.add("_source"); // add this field
SearchResponse response = transportClient.prepareSearch("programs")
.addFields(fields.toArray(new String[fields.size()]))
.execute().actionGet();