filter properties with Objectify 4 - google-app-engine

I'm trying to filter with Objectify in GAE:
List<users> ul = ofy.load().type(Usuario.class).filter("name", "gildus").list();
In the User's class use anotation #Index:
#Entity
public class Users {
#Id
private Long id;
#Index
private String name;
...
The filter result is empty, although there is value "gildus". When I use the ID field if it shows results (....filter("id", "1").list() ).
What more could I do to make it work ?

When I use the ID field if it shows results (....filter("id", "1").list() ).
Don't use filter for id. Use the following instead:
Usuario user = ofy.load().type(Usuario.class).id(1).get();

Related

Populate data by only using the id from another collection

I am building a table in React front end , I have and array list filled with id's.I want to populate the table by only using the Id's.
The Ids are filled in my customer collection
public class Customer {
#Id
private String id;
private String username;
private List<LinkedUsersID>linkedUsersId;
public class User{
#Id
private String id;
private String name;
private String surname;
private List<LinkedUsersID>linkedUsersId;
Someone metioned to me that I can reffrence the ids to a mongo collection and the data will populate itself in the table. Use Id to refer to the user collection and get data with that specific id and populate the Table
Can someone please explain or share a link on how this works.
use $lookup in aggregation like this
{
$lookup:{
from:"user" ,// user collection
localField:"linkedUsersId",
foreignField:"id",
as:"newUserField"
}
}
now run this aggregate on customer collection and returns user data in newUserField

Spring data JPA inserting null into column error even though I POST a value?

I want to save both child and parent entities whenever a POST call is made. I have an Item entity with a one to one mapping to a parent table Attribute:
#Entity
#Table(name="Item")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Item
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="attr_id")
private Attribute attribute;
#OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval=true)
private List<ValueSet> valueSets = new ArrayList<>();
// Other fields, getters, setters, overriding equals and hashcode using Objects.equals() and Objects.hashCode() for all the fields, helper for adding and removing ValueSet
}
The Attribute entity looks like this:
#Entity
#Table(name="Attribute")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Attribute
{
#Id
#Column(name="id")
private Long id;
// Other fields, getters, setters, NOT overriding equals hashCode
}
Whenever an Item gets saved I need the Attribute to get saved as well. I've my postman sending JSON POST data as follows:
{
"attribute":{
"id":"6"
},
"valueSets":[
{
"value":"basic"
}
]
}
My handler looks like this:
#PostMapping("/item")
public void postItems(#RequestBody Item item)
{
itemRepository.save(item);
}
ItemRepository is just a one liner with #Repository annotation:
public interface ItemRepository extends CrudRepository<Item, Long>
When I try to save the Item I run into - Cannot insert the value NULL into column 'attr_id', table 'Item'; column does not allow nulls. INSERT fails.
I can't figure out why is it unable to take the id value of 6 that I am supplying as part of my POST invocation. The id value 6 already exists on the Attribute table. I have also tried making the relationship bi-directional using mappedBy and CASCADE.ALL but still get the same error.
Any thoughts/suggestions on what I'm messing/missing? Also, is there a better approach to handle nested entities? Should I try to save each of them individually? In that case can the #RequestBody still be the parent entity?
I have built an example project, and try to replicate your situation, not successful. I am able to insert the "item" without any issue.
I placed the project under this repository https://github.com/hepoiko/user-5483731-1
Hope this help you to troubleshooting further or let me know If I miss anything in there.

Objectify Query by list's element

I am using Objectify to create an entity:
#Entity
public class Collection {
#Id
private String name;
#Index
private List<Long> viewersIds;
//other fields
}
Now I am trying to retrieve the list of Collections which have a particular viewerId, lets say 1. I have tried:
List<Collection> usersCollections = ofy().load().type(Collection.class).filter("viewersIds",1).list();
and
ofy().load().type(Collection.class).filter("viewersIds =",1).list();
and
ofy().load().type(Collection.class).filter("viewersIds ==",1).list();
Getting all Collections works using:
ofy().load().type(Collection.class).list();
What am I doing wrong?
Thank you!
EDIT:
Changing the Colllection object to contain a list of strings viewerIds instead of Long
#Index
private List<String> viewersIds;
And then query it with:
ofy().load().type(Collection.class).filter("viewerIds", value).list();
works. So this could be a solution if the list can be of Strings.
One thing to check is that viewerIds is indeed indexed in the entities that are supposed to be returned: https://console.cloud.google.com/datastore/entities/query
You're looking for 'in'
.filter("<collection> in", value)

Objectify: Filter by an attribute of collection entries?

I'm using Objectify on Google's AppEngine.
I have the following Entity-Model:
#Entity
public class ChallengeEntity {
#Id
private Long id;
#Index
public List<ChallengeParticipant> participants;
}
The Participant (not an entity... should it be one?)
public class ChallengeParticipant {
#Load
public Ref<UserEntity> user;
// ... participant-specific attributes
}
And the User-Entity:
#Entity
public class UserEntity {
#Id
Long id;
#Index
public String email = "";
}
Now how would I find all challenges for a given user-email?
Something along:
ofy().load().type(ChallengeEntity.class).filter("participants.user.email", "test#local.foo")
I am willing to adapt my entity-model to GAE's needs... how may I support this query efficiently and keep a nice model?
Thanks alot
Assuming your list of ChallengeParticipant is reasonably bounded (a few hundred at most) and you aren't at risk of hitting the 1M per-entity size limit, you're probably best leaving it as embedded.
To perform your query, first lookup the person by email, then filter by person:
UserEntity user = // load user (or get the key) by email
ofy().load().type(ChallengeEntity.class).filter("participants.user", user);
Note that you need to #Index the ChallengeParticipant.user field, not the ChallengeEntity.participants list.
Assuming that email is unique for a user, I'd keep ChallengeParticipant as a separate entity and maintain 2 way relationship with ChallangeEntity:
public class ChallengeParticipant {
#Id
String email; // must be able to uniquely identify a user.
List<Ref<ChallengeEntity>> challenges;
// ... participant-specific attributes
}
ChallengeEntity will exist as is but without any #Index
#Entity
public class ChallengeEntity {
#Id
private Long id;
public List<Ref<ChallengeParticipant>> participants;
}
When you want to add a new participant to a challenge, update both entities (Participant & Challenge) in one transaction. As there are no indexes involved, you'll always get consistent results.

GAE jpa database model example

I am totally new at this, I am sorry if it is stupid question.
I am trying to design database model for Google App Engine in JPA, but I am unable to get it right. When I find the way I can't get annotations right or I am getting error about M:N not supported in Google App Engine.
I need entity user to have multiple groups and groups have multiple users and there are users who are also group admins.
My basic model was User -> usergroup(user; group; (bool)isAdmin) <-Group
Can somebody give a clean and simple example of how to define relationships?
Please try this.
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private UserGroup usergroup;
}
class userGroup
#Entity
public class UserGroup {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
private String name;
private boolean admin;
#OneToMany(mappedBy = "usergroup", cascade = CascadeType.ALL)
private List<User> users = new ArrayList<User>();
}
please be noticed GAE have limitation on JPA you can read more here
I don't know anything about Google App Engine, but I can help with JPA though.
The problem here is the "isAdmin" column, which prevents the data model to be a simple #ManyToMany relationship with a joiner table.
With the introduction of this field, in the data model you need a Map on the User entity with key=Group and value=isAdmin, similarly you need a corresponding Map in the Group entity in order to know if each User is an admin.
This is modeled with #ElementCollection in the following way:
#Entity
#Table(name="User")
public class User
{
#Id
#GeneratedValue(strategy= GenerationType.TABLE)
private int id;
private String name;
#ElementCollection
#CollectionTable(name="Users_Groups", joinColumns={#JoinColumn(name="userId")})
#MapKeyJoinColumn(name="groupId")
#Column(name="isAdmin")
private Map<Group, Boolean> groups;
}
#Entity
#Table(name="Group")
public class Group
{
#Id
#GeneratedValue(strategy= GenerationType.TABLE)
private int id;
private String name;
#ElementCollection
#CollectionTable(name="Users_Groups", joinColumns={#JoinColumn(name="groupId")})
#MapKeyJoinColumn(name="userId", insertable=false, updatable=false)
#Column(name="isAdmin", insertable=false, updatable=false)
private Map<User, Boolean> users;
}
The important annotation is #ElementCollection, the other annotations are just to name the specific columns of the collection table and make sure they match from both entities: #CollectionTable gives the name of the table and the name of the column representing the id in the current entity. #MapKeyJoinColumn gives the name of the column representing the id of the "key" element in the Map, and #Column gives the name of the "value" element in the map.
I'm not sure if the insertable=false and updatable=false are needed in one of the entities, might avoid adding duplicate rows due to the cyclic dependency between User and Group.
Also you need to manually create the collection table, because at least EclipseLink tries to create it with two "groupId" and "isAdmin" columns. You might consider reviewing the design if it is absolutely needed a cyclic dependency between User and Group.

Resources