Object API binding : only fetch subobject id - orientdb

Is it possible to only store the id of subobject as a String attribute when retrieve an Object from database with database.load("objectId") ?
see documentation here : https://orientdb.com/docs/3.0.x/java/Object-DB-Attach.html
More informations
What I see possible with the documentation but that's not enough for me :
The POJO
class Person {
#Id
private String id;
private Address address;
}
class Address {
#Id
private String id;
// Not loaded using lazy loading
private String city;
}
The corresponding built object :
{
"id": "#10:10",
"address": {
"id": "#15:2"
}
}
What I want
POJOs are identical except from address field which is a String now.
class Person {
#Id
private String id;
private String address;
}
// I didn't add again the code for Address POJO
The sought JSON :
{
"id": "#10:10",
"address": "#15:2"
}

Related

Check if embbed document have data another document: MongoDB

I'm learning MongoDB and Mongo Spring, and I have somethings to wonder.
I have a UserInfo document, a user can have multiple roles (document Roles). I insert as a Set, work good. But for the time being, I can insert a role, which not exist in document Roles.
For the example below, I insert roles as ADMIN2, while Document Roles only having "ADMIN", "USER" and "MOD"
I have a document named User:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User implements UserDetails,Serializable {
#Id
private String id;
private final static String LOGIN_REGEX = "^(?>[a-zA-Z0-9!$&*+=?^_`{|}~.-]+#[a-zA-Z0-9-]+(?:\\\\.[a-zA-Z0-9-]+)*)|(?>[_.#A-Za-z0-9-]+)$";
#NotNull
#Field
#Size(min = 1, max = 50)
private String username;
#NotNull
#Field
//#Pattern(regexp = LOGIN_REGEX)
private String password;
#JsonIgnore
private Set<Roles> roles;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
Set<Roles> role = this.roles;
for(Roles roleItem : roles) {
authorities.add(new SimpleGrantedAuthority(roleItem.getCode()));
}
return authorities;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
the UserInfo extends User
#Document
#Data
#AllArgsConstructor
#NoArgsConstructor
public class UserInfo extends User implements Serializable {
public UserInfo(String id, #NonNull String username, #NonNull String password, Set<Roles> roles) {
super(id, username, password, roles);
}
#Field
#NotNull
private String firstName;
#NotNull
#Field
private String lastName;
#Transient
#Getter(AccessLevel.NONE)
private String fullname;
#Field
#NotNull
#Email
private String email;
#Field
private String description;
#Field
private String title;
#Field
private String phoneNumber;
#Field
private String lang;
public String getFullname() {
if(StringUtils.isBlank(lang))
if(lang.equals("VI"))
return lastName + " " + firstName;
else
return firstName + " " + lastName;
return null;
}
}
My idea is, a User can have a lot roles (for now, i have "ADMIN", "MOD" and "USER")
Here is document Roles
#Document("roles")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Roles implements Serializable{
#Id
private String id;
#Field
private String code;
#Field
private String name;
}
Here how the document UserInfo look like:
{
"_id": {
"$oid": "638b72f79c9b3a78b623ea50"
},
"firstName": "truong",
"lastName": "hoang ngoc nghia",
"email": "truonghnn23232",
"title": "Dev",
"lang": "VI",
"username": "truonghnn",
"password": "$2a$10$Jsn1wPMdr.TlS8yyjQ6mF.OBTdrxTuaaDQ8Xz30hSWsKFRuB2bfKW",
"roles": [
{
"code": "ADMIN"
}
],
"_class": "com.example.Auth_ToDo.Domain.UserInfo"
}
So, the issue is, when I input the roles to UserInfo document, I use JSON like this:
"roles" : [
{"code":"ADMIN2"}
]
Everythings is running fine. But as you can see, roles here having value of ADMIN2, which not exist in document Roles (Document Roles having ADMIN, USER and MOD as roles.code)
How can I implement my code, so when I insert into UserInfo document, it check if my role code exist in document Roles? If not, it will return an exception? (I want it to check by default)
I tried to use Embbed Document, as using #DocumentRef, but not working. The result is
=
"roles": [
null
],
"_class": "com.example.Auth_ToDo.Domain.UserInfo"
}
The role returned as null when i input code as "ADMIN"

method in ArangoRepository extension class using COLLECT in query annotation to group by and count not working

I have a simple node like this below
#Document("users")
public class User {
#Id // db document field: _key
private String id;
#ArangoId // db document field: _id
private String arangoId;
private String firstName;
private String lastName;
private String country;
public User() {
super();
}
public User(String id) {
this.id = id;
}
public User(String id, String country) {
this.id = id;
this.country = country;
}
// getter & setter
#Override
public String toString() {
return "User [id=" + id + ", name=" + firstName + ", surname=" + lastName + "]";
}
public String getId() {
return id;
}
}
here is the repository class but the method getListOfCountryAndNumUsers returns null even though i have inserted users with different countries into the database.
public interface UserRepository extends ArangoRepository<User, String> {
#Query("FOR u IN users COLLECT country = u.country WITH COUNT INTO length RETURN
{\"country\" : country, \"count\" : length }")
Iterable<CountryAndNumUsers> getListOfCountryAndNumUsers();
}
I think the problem could be with the the syntax of my query in the query annotation. I didnt see any direct example of using collect operation in the spring data arango db part of arangodb documentation here but I saw the collect operation in the section "high level operations" of arangoDb documentation here
Please Help. Thanks. !
So I discovered my error. It was in a class I didn't add in the question. That is the class for the return object of the method getListOfCountryAndNumUsers()
i.e class CountryAndNumUsers.
public class CountryAndNumUsers {
private String country;
private Integer numberOfUsers;
public CountryAndNumUsers(String country, Integer numberOfUsers) {
this.country = country;
this.numberOfUsers = numberOfUsers;
}
public String getCountry() {
return country;
}
public Integer getNumberOfUsers() {
return numberOfUsers;
}
}
so there was a mapping mismatch since the query returns an object with different field names. I changed the query to this below so that it matches
#Query("FOR u IN users COLLECT country = u.country WITH COUNT INTO length RETURN {\"country\" : country, \"numberOfUsers\" : length }")

Spring boot JPA - Custom Repository for multiple Entity

I've got some difficulties with my JPA Rest Project.
I have build my repositories for each of my entity (my tables in my database), and it works fine.
For example, a part of my entity "Personne" :
#Entity
public class Personne {
private Long id;
private String nom;
private String prenom;
private Date dateNaissance;
private String telDomicile;
private String telPortable;
private String telAutre;
private String telCommentaire;
private String fax;
private String mail;
private String commentaire;
private Timestamp dateSuppr;
private String sexe;
private Patient patientById;
private Adresse adresseByAdresseId;
#Id
#JsonProperty(value = "dataId")
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
And myRepository with a #Query :
#Transactional
#RepositoryRestResource(collectionResourceRel = "personne", path = "personne", excerptProjection = InlinePersonne.class)
public interface PersonneRepo extends JpaRepository<Personne, Long> {
#Query("from Personne p where p.nom = ?1 and p.prenom = ?2")
public Personne customRequest(String nom, String prenom);
}
My problem : the return result is always a type "Personne".
I would like to make a native request that sends me back an object, with customized properties.
Example of the wished return :
{object :
{name : String,
surname : String,
age : int },
adresse :{
city : String,
street : String
}
}
Is it possible to do that ?
I really need it because I have to make complex requests on many tables.
Thank you.
You could use interface-base projections:
First you create interfaces that reflect the fields you need:
interface PersonSummary {
String getName();
String getSurename();
int getAge();
AddressSummary getAddress();
interface AddressSummary {
String getCity();
String getStreet();
}
}
Then you indicate your custom query what interface it needs to extend and instantiate to populate the information:
public interface PersonneRepo extends JpaRepository<Personne, Long> {
// All your other abstract method
// Brand new query
#Query("Select p.name, p.surname, p.age, p.city, p.street from Personne p where p.nom = ?1 and p.prenom = ?2")
public PersonSummary customRequest(String nom, String prenom);
}
You would be receiving an object like this:
{
name : String,
surname : String,
age : int,
address :{
city : String,
street : String
}
}
You would need to test how flexible is this functionality in the terms of the composition complexity of the object you want to receive.

Querying Embedded document in MongoDB using Mongo Template

I have the above domain structure where I have list of Companies in the product and the aim is not make entry in mongoDB when I have exact match for companies & productId already present in the DB.
#Entity
public class Mobile {
#Id
private Integer id;
private String imei;
private Product productInfo;
// ...
}
#Entity
public class Product {
#Id
private Integer id;
private String productId;
private List<Company<?>> companies;
// ...
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(name= "samsung", value = Samsung.class),
#JsonSubTypes.Type(name= "htc",value = Htc.class)})
public class Company<T> implements Serializable {
private static final long serialVersionUID = -8869676577723436716L;
private T companyInfo;
private String type;
// ...
}
I am using mongo template and I have tried to use find as shown below but id didn't work
template.find(Query.query(Criteria.where("product.companies").is(companList),Mobile.class);

Super class elements not returned with class in morphia and mongoDB with jersey

I have base class as
#XmlRootElement
public abstract class BaseDO {
#Id
protected ObjectId id;
/**
* We'll only provide getters for these attributes, setting is done in #PrePersist.
*/
protected Date creationDate;
protected Date lastChange;
.....and user class as:
#Entity(value = "user", noClassnameStored = true)
#XmlRootElement(name = "user")
#XmlSeeAlso({BaseDO.class})
public class AtsUser extends BaseDO {
public static enum UserStatus {
CREATED, ACTIVE, INACTIVE, DELETED, CLOSED
}
#Indexed(unique = false)
private String firstName;
#Indexed(unique = false)
private String lastName;
#Indexed(unique = false)
private String email;
private String password;
#Embedded
private List<UserRoleDO> roles = new ArrayList<UserRoleDO>();
// private String userId; //TODO add this later
private UserStatus status;
private String success;
.....
the REST API is as follows:
#Path("user/validate")
public class AtsUserValidationService {
private AtsUserDao dao;
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
#GET #Path("/query")
#Produces(MediaType.APPLICATION_JSON)
public AtsUser getUserByEmailn(#QueryParam("email") String email) {
System.out.println("in getUserByEmailn");
dao = new AtsUserMongodbDao();
System.out.println("firstName " + email);
AtsUser atsUser = dao.getAtsUsersByEmail(email) ;
return atsUser ;
}
....
The morphia Dao is as follows:
#Override
public AtsUser getAtsUsersByEmail(String email) {
AtsUser atsUser = null;
if ((email == null) || email.isEmpty() ) {
return null;
}
System.out.println("getAtsUsersByEmail:" + email);
Query<AtsUser> query = mongoDatastore.find(AtsUser.class);
query.field("email").equal(email);
atsUser = query.get();
return atsUser;
}
.....
When I debug, I see the id field and creationDate fields in the java code, but the JSON does not contain that. Here is what my JSON looks like.
{
"id": null,
"code": "admin",
"desc": "admin",
"email": "admin#aa.com",
"firstName": "admin",
"lastName": "admin",
"password": "admin",
"status": "CREATED"
}
Why my id is null and how can i get elements from base class to show up in the JSON ?
I believe you need to annotate the base class with #Entity as well. It worked for me (using morphia 0.109).