Spring Data Mongo nested id won't work - spring

Does Spring Data treats mongo nested "id" attributes differently? I explain my problem: I have collection matches with the following structure
"teams": [
{
"id" : "5601",
"name" : "FC Basel"
},
... // more
]
When I want to retrieve all the matches which has team id 5601 I execute the following query
db.matches.find({ "teams.id" : "5601"})
Which works perfectly and returns some objects.
When I make a method
public List<MatchMongo> findByTeams_id(String id);
on my MatchRepository interface I get 0 results back while there are.
Logs shows
Created query Query: { "teams.id" : "5601"}, Fields: null, Sort: null
find using query: { "teams.id" : "5601"} fields: null for class: class
MatchMongo in collection: matches
So the query he makes seems to be the right one... :S
Trying with other fields (referee.name for ex.) works.
I even tried with the #Query annotation, but can't get it to work
Is there another solution? Is this a bug or am I doing something wrong?

Oh found the solution:
MatchMongo had List<TeamMongo> teams; on whereI had
#Id
private String id;
#Field(value = "id")
private String teamIdAttr;
So the method should be called
public List<MatchMongo> findByTeams_teamIdAttr(String id);
Never thought the method name should reflect objects attributes instead of collection structure
Thanks #martin-baumgartner your comment helped to solve this :)

Related

MongoDb spring boot jpa #Aggregation _id deserialization problem

Below aggregation always produces _id that looks like this.
"_id": { "timestamp": 1675104059, "date": "2023-01-30T18:40:59.000+00:00" },
and I need like this :
"_id": "63d80f2ddf20b2268a986dbf"
#Aggregation(pipeline = {"{'$match': {'userId': '?0'}}","{'$project': {'allEventsOfUser': 1}}","{'$unwind': {'path': '$allEventsOfUser'}}","{'$match': {'allEventsOfUser.date': {'$gte': ?1, '$lte': ?2}}}"}) List<?> findByUserIdAndDateRange(String name, Date dateStart, Date dateEnd);
I do not understand why the aggregation produces different result. I have tried all variants of JsonIgnore it does nothing when added to the field, nor does adding to the setter or getter. Can someone please help me, its screwing up my whole update flow, i need actual id not some funky useless object in my case.
public class EventItem { #Id public String _id;
it hjas something to do with aggregation but im new to mongodb and i have no idea how to stop this. Much thnx for anyone who helps!
You need to specify the id type:
#Field(targetType = FieldType.STRING)
public String id;
I do NOT know why this breaks with #Aggregation annotation, there were NO problems with same api with different query like find all.

Get String from SQL function, no entity, kotlin

Im confused..
I need to use Oracle function to retrieve just a single String, No entity.
So i try to use CrudRepository, but that dosent work without Entity?
interface UserRepository : CrudRepository<Contact, String>{
#Query(nativeQuery = true, value = "SELECT schema.get_user(:id) FROM DUAL")
fun getUser(id: String): String?
}
or
interface UserRepository : CrudRepository<Contact, String>{
#Query(nativeQuery = true, value = "SELECT schema.get_user(:id) AS name, '' AS email FROM DUAL")
fun getUser(id: String): String?
}
where i try to name returning string to fit entity i seem to be forced to use.
Entity Contact is super simple entity with two attributes.
#Entity
data class Contact(
#Id
val name: String?,
val email: String?
)
Function will only ever return one string, but i cant figure how would i insert that as a name.. With this Query i get ORA-00904: : invalid identifier most likely because i have no idea how to match identifier returned from function.. (SQLdeveloper gives function name as column name but the returned string dosent really have ANY column name, since it is calculated...)
I can't do a repository for a String either, can i?
EDIT: trying to clarify what i need:
Entity has two attributes, just one comes from the Query including function, other one must be fetch from other side of the world. How do i run this query and return either single string or entity (with email as null) only have gotten array of errors so far, thanks

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.

is ObjectId faster than String in fetching?

I'm trying to make the correct annotations for best performances
I have this collection : posts that has field author which is annoted string but contains the _id of another collection which is users :
users{
_id:objectId(BLABLA)
}
posts{
author : "BLABLA"
}
I want to know if I'm fetching posts by user as strings , is faster than fetching as objectId ?
thanks for answers..

PMD XPath rule that finds methods that use a class field whose name is not known ahead of time

I have a requirement to look for JPA persistent classes that use the JPA ID attribute in its equals() method. For example, the following class would trigger a PMD rule violation:
#Entity
public class Foo
{
#Id
private long id;
public boolean equals(Object o)
{
if (o.getClass().equals(Foo.class)) {
Foo other = (Foo) o;
return o.id == id;
}
return false;
}
}
I know how to get the various pieces of this query to work, but not how to put it together. So, for instance, I know how to find a JPA persistent class (assuming the use of JPA annotations):
//ClassOrInterfaceDeclaration/../Annotation/MarkerAnnotation/Name[#Image='Entity']
I know how to find the declaration of a field annotated with the JPA ID annotation:
//FieldDeclaration[../Annotation/MarkerAnnotation/Name[#Image='Id']]
Likewise, I can find an expression in the equals() method that references a field named 'id':
//MethodDeclaration[
./MethodDeclarator[#Image='equals'] and
./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[#Image='Object']
]
/Block//PrimaryExpression/PrimaryPrefix/Name[#Image='id']
The trouble I'm having is using the expression to find the name of the field marked with the #Id annotation, and using it in the predicate to find the line in the equals() method that uses that field.
Here's my best guess at a query, but it returns no nodes:
//MethodDeclaration[
./MethodDeclarator[#Image='equals']
and
//MethodDeclarator[count(./FormalParameters)=1]
and
./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[#Image='Object']
]
/Block//PrimaryExpression/Name[
#Image=ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/#Image='Id']/VariableDeclarator/VariableDeclaratorId/#Image
]
The first 7 lines returns all MethodDeclarations that have the name "equals", and takes a single "Object" argument.
The next section selects any PrimaryExpressions inside that method whose Name is equal to the name of a field that is annotated with the "Id" annotation.
Any help?
OK, I have figured it out... here is the solution I came up with:
//MethodDeclaration[
MethodDeclarator[
count(FormalParameters/FormalParameter)=1 and
#Image='equals' and
FormalParameters/FormalParameter[1]/Type/ReferenceType/ClassOrInterfaceType[#Image='Object']
]
]
/Block//PrimaryExpression[
PrimaryPrefix/#Image=
ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/#Image='Id'
] /VariableDeclarator/VariableDeclaratorId/#Image
or
PrimarySuffix/#Image=
ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/#Image='Id'
] /VariableDeclarator/VariableDeclaratorId/#Image
]
It seems to work.

Resources