spring-data-mongodb using the fieldName instead of _id - spring-boot

I have a Pojo with an attribute as
Class A{
#Id
#Field("item_id")
private String itemId;
}
When i try to update a document in MongoDB collection based on the itemId as below, it worked well and able to see from mongo ops logs that the query was transformed as "_id in itemIds "
Query query = new Query(Criteria.where("itemId").in(itemIds));
Update update = new Update();
update.set("field2", "abd");
mongoTemplate.updateMulti(query, update, A.class)
When i upgraded to spring-data-mongodb-2.1.5.RELEASE, the query i saw in the mongo logs was "item_id in itemIds". Since item_id is not a field and no index for that field in the collection, the query took forever to complete.
Any help to understand why the spring-data library is building the query as _id in older version and using the field as it is in newer version?

After a 2 minute search on the Spring documentation (https://docs.spring.io/spring-data/mongodb/docs/1.3.3.RELEASE/reference/html/mapping-chapter.html):
The following outlines what field will be mapped to the '_id' document field:
A field annotated with #Id (org.springframework.data.annotation.Id) will be mapped to the '_id' field.
A field without an annotation but named id will be mapped to the '_id' field.
Did you try that already?

Related

SpringData ElasticSearch insert/update multiple documents

My goal is to do insert and update multiple documents in ElasticSearch using ElasticsearchRepository.
public interface EmployeeInfoRepository extends ElasticsearchRepository<EmployeeInfo, String> {
}
However, whenever I call saveAll(entities), the number of document is unchanged but it creates new indexes for those entities.
employeeInfoRepository.saveAll(employeeInfos);
If I insert 1000 elements, at first it will have 1000 docs and 1000 indexes, which is what I expected. Then I call saveAll two more times, it still has 1000 docs but now the number of indexes increases to 3000.
How can I update it properly?
It would be the best if it's just as easy as calling saveAll and the rest is handled by SpringBootData ElasticSearch.
Update 1:
There is no change with the data, however when I run saveAll, the storage_size keeps increasing. Not sure if it creates the indexes again and still keeps the old indexes.
If you define the id in your document class, elasticsearch updates/inserts the document with the same document id value.
Here an example:
#Document(indexName = "example_index")
public class Example {
#Id
#Field(type = FieldType.Long)
private long id;
}
Of course, you have to handle the logic for a unique id in your project.

Update by query multiple fields using Spring Data Elasticsearch?

I want to update all the documents that have for exemple the same name. I've seen in the elasticsearch documentation that I can use _update_by_query. So I tried to implement it in my repository like this:
#Query("{\"script\": { \"inline\": \"ctx._source.name = ?1\"; \"ctx._source.username = ?2\"; \"ctx._source.avatar = ?3\", \"lang\": \"painless\" }, \"query\": { \"match\": { \"name\" : \"?1\" }}")
List<User> update(String name, String username, String avatar);
But I get the following error:
nested exception is ElasticsearchStatusException[Elasticsearch exception [type=parsing_exception, reason=[script] query does not support [inline]]]
at org.springframework.kafka.listener.SeekUtils.seekOrRecover(SeekUtils.java:157) ~[spring-kafka-2.5.0.RELEASE.jar:2.5.0.RELEASE]
Edit 26.06.2020:
This answer is not correct, I added a correct on.
Old incorrect answer:
Seems strange to me, that this error comes from org.springframework.kafka.listener.SeekUtils.
To update using a script, you can use the update(UpdateQuery updateQuery, IndexCoordinates index) of a ElasticsearchOperations instance.
To have this in your Repository, you will need to create a repository cusomization like it is described here. In the implementation, autowire a ElasticsearchOperations instance. In this custom repository interface, you define the method
List<User> update(String name, String username, String avatar);
In the implementation, build up a UpdateQuery object with the script and the other information and pass this to the ElasticsearchOperations instance.
After checking the code of Spring Data Elasticsearch, I need to withdraw what I wrote in the first answer:
Currently Spring Data Elasticsearch does not support update by query. It is only possible to update entities with a know id either in a single operation or in a batch update.
I created an issue in Jira to add support for that.

How to set OpType on IndexQuery in Spring Data Elasticsearch

Assume spring-boot-starter-data-elasticsearch version 2.1.0.RC1.
Take the following, simple implementation for indexing an entity:
IndexQuery indexQuery = new IndexQueryBuilder().withId(entity.getId()).withObject(entity).build();
String id = elasticsearchTemplate.index(indexQuery);
How do I set the OpType.CREATE on this operation, so that I can assure only documents get indexed which don't already exist?
The equivalent REST API request would look like the following:
POST /{index}/{entity id}?op_type=create
{
"id" : "{entity id}",
"attribute" : "value"
}
This is not supported at the moment by Spring Data ES.
There's a open issue that reports exactly that feature, you might want to check it out: https://jira.spring.io/browse/DATAES-247

What exactly spring-data-mongodb do when calls modelRepository.save()?

For example I have a model:
#Document(collection = "events")
public class Event {
#Id
private String id;
private String value1;
private Spring value2;
}
And some code in the service class:
Event event = eventRepository.findOne("1");
event.setValue1("newValue1");
eventRepository.save(event);
Does Spring Data update all fields for the document or only changed fields?
In this case what's about field2, will it be updated with the old value?
How can I turn on logs to check what exactly spring data do?
logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG
This one turn on logs for the query only, not for the update:
016-10-10 09:39:25.938 DEBUG 11417 --- [ restartedMain] o.s.data.mongodb.core.MongoTemplate : findOne using query: { "_id" : "1"} in db.collection: t87.events
2016-10-10 09:39:25.965 DEBUG 11417 --- [ restartedMain] o.s.data.mongodb.core.MongoTemplate : Saving DBObject containing fields: [_class, _id, value1, value2]
MongoRepository.save() calls MongoDB db.collection.save behind the scenes . Depending on the value of id it may insert / upsert / replace the entire document.
So, in answer to your question:
Does Spring Data update all fields for the document or only changed fields? In this case what's about field2, will it be updated with the old value?
All fields are updated (upserted) including field-2 with the old value.
In order to set only field-1 - which is more efficient - you will have to use MongoTemplate in conjunction with an Update and a $set operator.
In order to see what's going on, you better look at the MongoDB log to see how update operations being handled. See setProfilingLevel on how to do capture each write operation; you will probably have to record each operation by setting the profiling level to 2. Don't forget to turn it off afterwards.

Spring data jpa Query dynamically pass where clause

My Entity is in this way
public class event
{
String title;
String description;
String city;
}
I am new to Spring data jpa ,i want implement search feature when an user enters "Hello Hyderabad Fest"
I want token size the string and split into words and find Any word matches on any properties on entity with search query hit to db.
WHERE title LIKE '%Hello%' OR title LIKE '%Hyderabad%' OR title LIKE
'%Fest%' OR description LIKE '%Hello%' OR description LIKE
'%Hyderabad%' OR description LIKE '%Fest%'city LIKE '%Hello%' OR
cityitle LIKE '%Hyderabad%' OR city LIKE '%Fest%'
How can we achieve this in spring data jpa.
Can we dynamically pass where condition in Spring data jpa named queries
Can we lucene kind query which we use in nosql dbs.
any other suggestion
Thanks in advance.
Postgresql fulltext search query solved the above issue http://rachbelaid.com/postgres-full-text-search-is-good-enough/

Resources