SpringData annotation(or the standard way) to use String for MongoDB ObjectId in java for manual references - mongodb

I am wondering if there exists a way to map String on the java side for manual references to ObjectIds and vice-versa. For example in:
User =[{_id: ObjectId('123'),
pics_id: ObjectId('123'), ...
}, ... ]
pics_id is a manual reference to another collection. The following code:
class User{
#Id id;
#Field("pics_id") String picId;
}
stores the pics_id as String instead of ObjectId.
Is there any way to make this happen without the use of the ObjectId class instead of String? IMHO, using ObjectId in the java code would make the code look a bit strange, as some ids are string(such as fields annotated with #Id) and some are objectIds. Thank you.

With the upcoming Spring Data MongoDB 2.2 release it is possible to define the desired target type via the #Field annotation.
The type information is passed down to the conversion subsystem so that eg. a plain String can be stored as Code or ObjectId.
class User {
#Id String id;
#Field(targetType = FieldType.OBJECT_ID)
String picId;
}
Please have a look at the documentation of 2.2.0.RC1 for more details.

Related

FallBack Mapping in Mapstruct

I am currently using mapstruct in my project. I have a target field 't1' which could be either mapped to source field 's1' or 's2', initially it should try to map the source field 's1' to target field 't1', in case it is null it should then fallback to source field 's2' for mapping it to the target field 't1'. And the source field objects in both cases are nested and would need some processing before it is mapped to the target. I've been looking around however I wasn't able to find any solution for this. Does Mapstruct support fallback Mapping? Below is an example, Here UserRequest is the target object and User is the source. In case I would like map id of the userRequest to user.address.postal primarily and in case it's null the id should be mapped to location.id of the overrideLocation. Can anyone please help me with this.
UserRequest{
String id;
}
User{
String name;
Address adress;
OverrideLocation location;
}
Address{
String postalCode;
}
OverrideLocation{
String id;
}
For now I've been using the AfterMapping in mapstruct to accomplish this. The primary mapping I specified as part of the #Mapping and the fallback mapping I've specified under AfterMapping. However I was wondering if there is a better way to deal with it. I looked into defaultValue and default expression as well, however I wasn't able to use it in this case

Hibernate Search: Find in list of intervals

I am using Hibernate Search 6.x within my Spring Boot application. I got an indexed entity with a set of date intervals.
#Indexed
public class ProudParent {
...
#IndexedEmbedded(includePaths = {"start", "end"})
Set<DateInterval> parentalLeaves;
}
And the class DateInterval looks like
#Embeddable
public class DateInterval {
#GenericField
LocalDate start;
#GenericField
LocalDate end;
}
That is my range query to search for all proud parents which were in parental leave on a specific date:
bool.must(factory.range().field("parentalLeaves.start").lessThan(date));
bool.must(factory.range().field("parentalLeaves.end").greaterThan(date));
Now the problem is that it finds proud parents which first parental leave was before date and the last parental leave was after date. So it does not search in the "same" date interval.
Can someone give me a hint of what I'm doing wrong?
Regards, Rokko
#IndexedEmbedded will "flatten" the object structure by default, so all starts and ends are mixed together in the index, with no way to know which end matches which start.
You can read more about this in this section of the reference documentation. In short, this default is mainly for performance, because preserving the object structure can be (very) costly on large indexes, and is usually not necessary.
The solution, in your case, would be to use a NESTED structure:
#Indexed
public class ProudParent {
...
#IndexedEmbedded(includePaths = {"start", "end"}, structure = ObjectStructure.NESTED)
Set<DateInterval> parentalLeaves;
}
Then make sure to tell Hibernate Search you want the matches on start and end to be on the same parentalLeave, using a nested predicate:
bool.must(factory.nested().objectField("parentalLeaves")
.nest(factory.bool()
.must(factory.range()
.field("parentalLeaves.start")
.lessThan(date))
.must(factory.range()
.field("parentalLeaves.end")
.greaterThan(date)))
Don't forget to reindex your data before testing.
Side note: the syntax should be slightly more convenient with the upcoming Hibernate Search 6.2.0.Alpha2 (not yet released):
bool.must(factory.nested("parentalLeaves")
.add(factory.range()
.field("parentalLeaves.start")
.lessThan(date))
.add(factory.range()
.field("parentalLeaves.end")
.greaterThan(date)))
Other side note: hopefully one day we'll have date ranges as a primitive type in Hibernate Search (HSEARCH-4199) and this whole discussion will become irrelevant :)

Is there a more advance way to handle Go Entgo postgreSQL error handling?

So I'm developing a API using Go together with ORM package Entgo and Postgres. Is there a way to handle the errors same or similar way as they are solved in pg package where I have all needed information why query failed?
All I found in ent go are this methods but they only return bool
ent.IsNotFound(err)
ent.IsConstraintError(err)
ent.IsNotLoaded(err)
ent.IsValidationError(err)
It would be great to have something similar like pg.Error:
type Error struct {
Severity string
Code ErrorCode
Message string
Detail string
Hint string
Position string
InternalPosition string
InternalQuery string
Where string
Schema string
Table string
Column string
DataTypeName string
Constraint string
File string
Line string
Routine string
}
So I asked this same question on package repo and this is the answer I got from repo Maintainer.
Ent wraps or returns the underlying driver errors. So, you can either use type-assertion or errors.Is/errors.As helpers to extract these types.
See examples in our integration-test:
https://github.com/ent/ent/blob/60e0328/entc/integration/integration_test.go#L1845-L1858
https://github.com/ent/ent/blob/60e0328/entc/integration/integration_test.go#L423

Query MongoDB with dynamic selector in Camel

I found a solution here: How do I create a dynamic equals query using Apache Camel and MongoDB?
But this looks like a lot of work. Doesn't Camel have a simpler way to pass values to a MongoDB query? I wish we could just pass the actual find({}) language that Mongo uses.
Here is what I have working, with some logging showing what it's doing:
.setHeader(MongoDbConstants.CRITERIA, new Expression() {
#Override
public <T> T evaluate(Exchange exchange, Class<T> type) {
Long drRequestId = exchange.getIn().getHeader("orderid", Long.class);
Bson equalsClause = Filters.eq("id", drRequestId);
return exchange.getContext().getTypeConverter().convertTo(type, equalsClause);
};
})
.log(MongoDbConstants.CRITERIA)
.log("${headers.CamelMongoDbCriteria}")
.to("mongodb:mongo?database={{spring.data.mongodb.database}}&collection=ftx_orders&operation=findOneByQuery")
did you try with ${body.id}?
Also, you can also send it in header, setting using
exchange.getIn().setHeader("id","value");
and then using the same way you mentioned above.
.setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", simple("${header.id}"))))

Delete by Object Id angular 2 and mongodb

I am trying to delete Posts from a comments section in my web app. Mongodb passes an objectId but I am unable to get it from my angular 2 front end. By default ObjectId is passed as _id so on my front end I call Post._id in my delete function and it passes through all this info
what I actually want is the unique ObjectId given by the database itself that look like this
How can I get this value on the front end of my application? I have all the code to my project on github located here with both my UI and API backend. Thanks for any help!
relative files from repo
UI/src/app/components - PostData.Service.ts
UI/src/app/components -postRand.component.ts
UI/src/app/components/models - Post.ts
API/src/controllers - PostAPIController.cs
API/src/models - Post.cs
API/src/models - DataAccess.cs
API Running
I believe I need to make this fix in the api layer because it is passing my _id as an object and not a string... This is just a guess of mine and I am not sure how to do this.
I found out how to solve my issue....
I had to go back into my model and convert my ObjectId to a string by parsing it out
[BsonRepresentation(BsonType.ObjectId)]
public string Id
{
get { return Convert.ToString(_id); }
set { _id = MongoDB.Bson.ObjectId.Parse(value); }
}
I then added my new Id field to all of my http calls changing out where I was calling by ObjectId, to now call upon my new string value Id
Now when I run my Api get the actual Id of my object
Lastly I added my newly generated Id field to my front end, replacing the old objectId value in my delete functions with the new Id.
All code has been updated in my git project, see file referenced in question for relevant documents.
After review it looks like you are trying to delete the object by an object id string instead of an object id object.
In PostAPIController.cs
line 74
objds.Remove(post._id);
This is looking for an object with a string value to match on.
Pretty sure it should be like this
objds.Remove(ObjectId.Parse(post._id))
This will construct a object id to match on for the deletion