I've been reading the MongoDB documentation and Spring adds a _class field by default to the stored data. Is there any way to use this information to have type inference?
For example: There is a an abstract class Animal with three subclasses Dog, Cat, Bird. Say you have a class Zoo which contains a list of animals. In the database you store those Zoo Objects. Is there any function to get a List<Animal> back with Animals that can be upcasted?
I'm using Spring so I prefer to have a solution that would work using the spring-data-mongodb. But an external mapping library would be fine too. I prefer not to write it myself as it seems basic mapping functionality.
Make sure you map all types you mentioned to be stored in the same collection (e.g. using the #Document annotation). Then you can simply execute queries against the collection handing in Animal to the according method on MongoTemplate. The underlying converter will then automatically instantiate the correct types based on the information stored in _class. The same applies to the usage of Spring Data MongoDB repositories.
Related
When using Grape Entity, sometimes we want to expose a few fields from an inner/related object. We can simply do this by:
expose(:bar) { |entity| entity.foo.bar }
However if many fields needs this treatment, this can get very repetitive. Is there a way to define delegation / forward so a bunch of expose all are associated with another object?
create a separate entity for foo class, let's call it API::Entities::Foo. then you can
expose :foo, using: API::Entities::Foo
you have to follow REST guidelines to serialize like this. you are dealing with resources. don't break it to flat, cumbersome data structures.
I am trying out reactive support in spring-data with MongoDB. I am using spring-boot 2.0.0.
Generally I would write a domain object like this in my project:
#Document
public class PriceData {
......
}
With this spring-data it would create a collection with name priceData in MongoDB. If I want to customize it, then I would do it using the collection attribute:
#Document(collection = "MyPriceData")
Since I want to try reactive support of MongoDB, I want to create a capped collection so that I can use #Tailable cursor queries.
I can create a capped collection in my MongoDB database as specified here:
CollectionOptions options = new CollectionOptions(null, 50, true);
mongoOperations.createCollection("myCollection", options);
or
db.runCommand({ convertToCapped: 'MyPriceData', size: 9128 })
This is not a big problem if I use some external MongoDB database where I can just run this command once. But if I use an embedded MongoDB, then I would have put this in a class which would be executed every time during start up.
Either way I would be creating a collection even before the first request. So I was wondering if there is a way, I could specify to spring-data-mongodb that I need a capped collection instead of regular collection.
Unfortunately #Document doesn't help in this case.
So below is from Oliver
Might be a good idea to have those options exposed to the #Document annotation to automatically take care of them when building the mapping context but we generally got the feedback of people wanting to manually handle those collection setup and indexing operations without too much automagic behavior. Feel free to open a JIRA in case you'd like to see that supported nevertheless.
This is back in 2011. And it seems its still true to date. If you really need the change to handle it using annotation, you should open a JIRA ticket
I'm guessing that the type is used for CRUD operations. Is it used for anything else besides that? I'm wondering what impact there could be from configuring how it gets populated.
The _class field is written to allow polymorphic properties in your domain model. See this sample:
class Wrapper {
Object inner;
}
Wrapper wrapper = new Wrapper();
wrapper.inner = new Foo();
couchbaseOperations.save(wrapper);
You see how the field inner will get Foo serialized and persisted. On the reading side of things we now have to find out which type to create an object of and the type information in Wrapper is not enough to do so as it only states Object.
That's why Spring Data object mapping persists an additional field (name customizable but defaulting to _class) to store that information to be able to inspect the source document, derive a type from the value written for that field and eventually map that document back to that particular type.
The Spring Data Couchbase reference documentation doesn't really document it, you can find information about the way this works in the docs for the MongoDB module. I've also created a ticket for Spring Data Couchbase to improve on the docs for that.
I was given a task to introduce solr to our product so I thought about spring-data-solr. I have seen this blog:
http://www.petrikainulainen.net/spring-data-jpa-tutorial/
and I was able to run embedded solr in integration test. Since I have a simple POC I wanted to make it more advanced to see whether it fits our needs. So I started to search for mapping nested objects. I found this:
https://stackoverflow.com/questions/30561245/is-is-possible-to-use-embeddables-in-spring-data-solr
Someone answered that version 1.4.0 did not support nested objects. Anyone knows whether it changed? These links look promising:
https://dzone.com/articles/using-solr-49-new
Solr: Indexing nested Documents via DIH
https://issues.apache.org/jira/browse/SOLR-1945
So, wrapping up, here is a list of my questions:
Is it possible to map parent-child relation? (on one level at least?)
If you answered 'no' to first question - then how can I flatten child's fields to be part of solr's document? Should I register some kind of converter somehow? Is there anything else I should do?
I found also this: http://docs.spring.io/spring-data/solr/docs/current/api/org/springframework/data/solr/core/mapping/Indexed.html What is the purpose of this annotation? So far I have seen example with #Id and #Field annotations only. Is it used to generate schema based on model maybe? If so then how can I do that?
Last, but not least - when I create a SolrRepository should I use my JPA entity (annotated with #Fields annotations) as a generic type? Or rather should I create a totally different POJO which should be a view/dto of my jpa entity? This question is again about conversion I guess. If I create a dedicated POJO than I can convert/map fields manually in constructor, but this feels rather bad idea.
I am working on a REST service which uses Spring 4.x. As per a requirement I have to produce several different views out of same object. Sample URIs:
To get full details of a location service: /services/locations/{id}/?q=view:full
To get summary of a location service: /services/locations/{id}/?q=view:summary
I have thought of two solutions for such problem:
1. Create different objects for different views.
2. Create same object, but filter out the fields based on some configuration (shown below)
location_summary_fields = field1, field2
location_detail_fields = field1, field2, field3
Could someone help me to understand what could be an ideal solution? I am not aware of any standard practice followed for this kind of problems.
Thanks,
NN
In my opinion the best option is to use separate POJOs for different views. It's a lot easier to document it (for example when you use some automated tools like Swagger). Also you've to remember that your application will change after some time, and then having one common POJO could make troubles - then you'll need to add one field to one service and don't expose it through another.
See this article on how google gson uses annotations to convert a Java Object representation to a json format : http://www.javacreed.com/gson-annotations-example/
Since you want two different representations for the same object you could roll your own
toJson method as follows :
a) Annotate each field of you model with either #Summary, #Detail or #All
b) Implement a toJson() method that returns a json representation by examining the annotations for the fields and appropriately using them
If you need an XML representation same thing, except you would have a toXML().