Dynamic document loading with #DocumentRererence for Spring Data MongoDB - spring-boot

Is there a way to stop loading the referenced document marked with #DocumentReference during an api call as it'd make the db calls heavy in case there are multiple referenced documents? Or is there better way to do that? I have tried #DBRef but that won't solve the problem as the existing database looks something like this:
{
"_id" : "833f7d",
"name" : "Del Rey Books",
"arconym" : "DRB",
"foundationYear" : 1977,
"books" : [
NumberLong(300000),
NumberLong(395652)
]
}
and #DBRef would make the db entry to look something like this if I save new data (therefore won't solve the problem) :
{
"_id" : "833f7d",
"name" : "Del Rey Books",
"arconym" : "DRB",
"foundationYear" : 1977,
"books" : [
{
"$ref" : "book",
"$id" : 300000
},
{
"$ref" : "book",
"$id" : 395652
}
]
}
The domain class looks something like this:
class Publisher {
// ...
#DocumentReference(lazy = true)
List<Book> books;
}
The GET api request fetches the whole referenced document in response body, but along with it also adds the keys (i) target - containing the same referenced document all over again. (ii) source - containing the id of the referenced object again. Something like this:
{
"_id" : "833f7d",
"name" : "Del Rey Books",
"arconym" : "DRB",
"foundationYear" : 1977,
"books" : [
{
"id" : 300000,
"isbn13" : "978-0345503800",
"title" : "The Warded Man",
"pages" : 432,
"target": {
id" : 300000,
"isbn13" : "978-0345503800",
"title" : "The Warded Man",
"pages" : 432,
},
"source" : 300000
},
{
"id" : 395652,
"isbn13" : "978-0345503800",
"title" : "The Sailor",
"pages" : 420,
"target": {
id" : 395652,
"isbn13" : "908-093830380",
"title" : "The Sailor",
"pages" : 420,
},
"source" : 395652
}
]
}
What is the significance of target, source all over again in the response body?
Also is there any other way to have references but not load the references in the response body during an API call? I was expecting (lazy = true) would do so, but it doesn't.

Related

MongoDB with inheritance relationship

I have below classes with relationship .
Job
-- name
-- description
-- List(Task)
Task
-- name
-- description
scriptTask extends Task
-- script
apiTask extends Task
-- apiMethond
-- url
when I save the Job with the both script and apitask value, save works fine. I could see the task's field name and description for both task's in db.
{
"jobName" : "jobName",
"tasks" : [
{
"script" : "whoami",
"name" : "script",
"description" : "script",
"_class" : "com.model.scriptTask"
},
{
"apiMethond" : "GET",
"url" : "/user",
"name" : "ansible",
"description" : "ansible",
"_class" : "com.model.apiTask"
}
]
}
But when I fetch the details using repository.findone(), I am not getting the task's name and description field
{
"userId": "5eeaf6584c24665e1cdaf400",
"jobName": "jobName",
"tasks": [
{
"script": "whoami"
},
{
"apiMethond" : "GET",
"url" : "/user",
}
]
}
How to get the super class fields from db.
I am using spring-boot-starter-data-mongodb to do CRUD operation.
Thanks for your help.

Mongoose + GraphQL (Apollo Server) Schema

We have db collection which is little complicated. Many of our keys are JSON objects where fields aren't fixed and change based on input given by user on UI. How should we write mongoose and GraphQL Schema for such complex type ?
{
"_id" : ObjectId("5ababb359b3f180012762684"),
"item_type" : "Sample",
"title" : "This is sample title",
"sub_title" : "Sample sub title",
"byline" : "5c6ed39d6ed6def938b71562",
"lede" : "Sample description",
"promoted" : "",
"slug" : [
"myurl"
],
"categories" : [
"Technology"
],
"components" : [
{
"type" : "Slide",
"props" : {
"description" : {
"type" : "",
"props" : {
"value" : "Sample value"
}
},
"subHeader" : {
"type" : "",
"props" : {
"value" : ""
}
},
"ButtonWorld" : {
"type" : "a-button",
"props" : {
"buttonType" : "product",
"urlType" : "Internal Link",
"isServices" : false,
"title" : "Hello World",
"authors" : [
{
"__dataID__" : "Qm9va0F1dGhvcjo1YWJhYjI0YjllNDIxNDAwMTAxMGNkZmY=",
"_id" : null,
"First_Name" : "John",
"Last_Name" : "Doe",
"Display_Name" : "John Doe",
"Slug" : "john-doe",
"Role" : 1
}
],
"isbns" : [
"9781497603424"
],
"image" : "978-cover.jpg",
"price" : "8.99",
"bisacs" : [],
"customCategories" : [],
},
"salePrice" : {
"type" : "",
"props" : {
"value" : ""
}
}
}
},
"tags" : [
{
"id" : "5abab58042e2c90011875801",
"name" : "Tag Test 1"
},
{
"id" : "5abab5831242260011c248f9",
"name" : "Tag Test 2"
},
{
"id" : "592450e0b1be5055278eb5c6",
"name" : "horror",
},
{
"id" : "59244a96b1be5055278e9b0e",
"name" : "Special Report",
"_id" : "59244a96b1be5055278e9b0e"
}
],
"created_at" : ISODate("2018-03-27T21:44:21.412Z"),
"created_by" : ObjectId("591345bda429e90011c1797e")
}
I believe Mongoose have Mixed type but how do i represent such complex type in Apollo GraphQL Server and Mongoose Schema. Also, currently my resolver is just models.product.find(). So if i have such complex type, need to understand what update needs to make to my resolver.
It will be great if i get complete solution for GraphQL Apollo schema, mongoose schema and resolver for my data.
Finally found solution for problem.
You can declare new type and reference it in typeDef for GraphQL Schema.
In mongoose model, you can reference it as {type: Array}

Javers querybuilder for anyDomainObject with commit property filter not working

The Javers JQL to get all domain objects returns empty list.
I've written a wrapper rest api and exposed the Javers commit and getAllShadows api's as below.
#PutMapping("/commit")
public <T> CommitEntity<T> commit(#RequestBody CommitEntity<T> committedObject);
#GetMapping("/getEntityShadows")
public List<EntityShadow> getEntityShadows(#RequestParam(name = "entityId") String entityId);
Now when I use the commit API(above), I'm able to commit my domain object to the repository (mongo)
Sample below:
{
"_id" : ObjectId("5c5f6fb51ebaa93b96edadc8"),
"commitMetadata" : {
"author" : "UserFName UserLname",
"properties" : [
{
"key" : "entityId",
"value" : "user001/US"
}
],
"commitDate" : "2019-02-09T16:26:29.543",
"commitDateInstant" : "2019-02-10T00:26:29.543Z",
"id" : NumberLong(8440229536252376064)
},
"globalId" : {
"valueObject" : "org.javers.core.graph.LiveGraphFactory$MapWrapper"
},
"state" : {
"map" : {
"userId" : {
"id" : "user001",
"locale" : "US"
},
"createdDate" : "2019-02-08T22:16:58",
"Name" : "User Fname",
"address" : {
"state" : "CA",
"country" : "US"
},
"authorName" : "UserFName UserLname",
"lastModifiedBy" : "2019-02-09T16:26:29"
}
},
"changedProperties" : [
"map"
],
"type" : "INITIAL",
"version" : NumberLong(1),
"globalId_key" : "org.javers.core.graph.LiveGraphFactory$MapWrapper/"
}
Now when I try to get all shadows as below, I get back an empty List. I expected to get all the shadows from the repo.
JqlQuery jqlQuery = QueryBuilder.anyDomainObject().withCommitProperty("entityId", "user001/US").build();
List<Shadow<Object>> shadows = javers.findShadows(jqlQuery);
Am I missing anything here?
I tried to just get the shadows with any filter like below, still got back an empty list
JqlQuery jqlQuery = QueryBuilder.anyDomainObject().build();
List<Shadow<Object>> shadows = javers.findShadows(jqlQuery);

Spring Boot MongoDB find records by value in list

I have in my mongodb collection with news.
{
"_id" : ObjectId("593a97cdb17cc6535522d16a"),
"title" : "Title",
"text" : "Test",
"data" : "9.06.2017, 14:39:33",
"author" : "Admin",
"categoryList" : [
{
"_id" : null,
"text" : "category1"
},
{
"_id" : null,
"text" : "category2"
},
{
"_id" : null,
"text" : "category3"
}
]
}
Every news record has list of categories. I woudl like to find all news who has category1 in categoryList I try do that by
newsRepository.findByCategoryList("category1"); but not working.
How to do that?
With your current repository method the generated query is
{ "categoryList" : "category1"}
What you need is
{ "categoryList.text" : "category1"}
You can create the query in two ways.
Using Repository
findByCategoryListText(String category)
Using Query Method
#Query("{'categoryList.text': ?0}")
findByCategoryList(String category)

Google Places API Returns a result far away from the search center

Here is a query that I believe should produces hotel with the same name very closed to the reference point.
https://maps.googleapis.com/maps/api/place/textsearch/xml?key=_your_api_key_goes_in_here_&sensor=false&language=en&location=56.1995,-4.746&radius=30000&query=ARROCHAR
As yo can see the location is 56.1995,-4.746. This is a place in UK. The query if for a hotel named Arrochar. The hotel does exist. The result look like this :
{
"html_attributions" : [],
"results" : [
{
"formatted_address" : "Arrochar, Staten Island, NY, USA",
"geometry" : {
"location" : {
"lat" : 40.59234250,
"lng" : -74.07407289999999
},
"viewport" : {
"northeast" : {
"lat" : 40.60012790,
"lng" : -74.05918419999999
},
"southwest" : {
"lat" : 40.5779020,
"lng" : -74.08570610
}
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"id" : "c7d9f74dca8676759bfe7ea168b8547cd6de3c5e",
"name" : "Arrochar",
"reference" : "CpQBiAAAAKYklx4_uV5ovlJP-x-fGr2VAqzhUCRQ2icNBXj2b5TkGZMqix3tL4xyTizwa0_UdZ5VDbI3psEagu0tTiFc2N6Awn2OJE4Oc3NXtXyaUlADLhJKwnZSuMFLFv85ia3AKiR9fFVWH96u6lEcC16foKMyFREY_KR6Z97QdShfiJCPYNlYZye49gsdU0UsIx3YbxIQa5LUZiMGZvW8sQHn_Cog-hoUr4bMXlYdo9Xae82ZRL-BEDSKRAw",
"types" : [ "neighborhood", "political" ]
}
],
"status" : "OK"
}
As one can see this place is in US and it is more than 5000 km away. Now, if one goes and modifies the query too look like this:
https://maps.googleapis.com/maps/api/place/textsearch/xml?key=_your_api_key_goes_in_here_&sensor=false&language=en&location=56.1995,-4.746&radius=30000&query=hotel+ARROCHAR
Then the correct result appear:
{
"formatted_address" : "Main Street, Arrochar, United Kingdom",
"geometry" : {
"location" : {
"lat" : 56.199560,
"lng" : -4.7459760
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "78d53766dfb2c3bb6008301b079423fffb78b801",
"name" : "Arrochar Hotel",
"reference" : "CnRtAAAAJPg2ABkegIT9Q12hABjfGezwGgHCc3ur1W761rhtkQq0n6Id-cgaLREU-g8Uo5Bnw4ovaAnqCrYm_fHEKjBHOrHK5dvcGpAndQVsl-zi_qZSZR6Sa5HvYZI4pA3ne3rNTl0m4TwuwmMM0nx2gSkxEBIQFqgW85GrUZI8SQFvohgMiBoU51C716M4m-ySUVECgT4BFZUYB50",
"types" : [ "lodging", "establishment" ]
}
So why is Places API text search acting like that? Note, the location parameter point to the exact place where the hotel is. Yet, I get something that is 5000 km away, unless I add the word 'hotel'.
Thanks
This is pretty old but just in case, I believe you should use nearbysearch instead of textsearch. (In your url)
Based on Google Places API documentation, your search has nothing to do with an specific location/distance.
Take into account that by using 'nearby search,' location and radius are required parameters. 'textsearch' just requires query and key.
Note: Radius might be required not to be included if using rankby=distance. Check the documentation for more details.
Good luck.

Resources