Optimizing foreign key & manytomany field in REST API query - rest

I'm wondering is there anyway to optimize an api when using foreign key and ManytoMany field, for example :
Serializer :
class SerializerA(serializers.ModelSerializer):
class Meta:
model = Model_A
fields = ('id', 'official_name', 'gender')
depth = 1
class SerializerB(serializers.ModelSerializer):
user = SerializerA(many=True)
class Meta:
model = Model_B
fields = ('id', 'project_name','project_type', 'project_start_date', 'user')
depth = 1
API :
class ReportAPI(APIView):
def get(self, request):
all_projects = Model_B.objects.all()
project_serializer = SerializerB(all_projects, many=True)
return Response(project_serializer.data)
now with this, if i go to the API url, and debug this page, it''l show that I'm querying 78 times from the SQL query. But if I remove one field from manytoMany seriealizer field which the 'gender', the page now will only query from the database 21 times, so my question is again, how can I optimize this?

You can use select_related (for ForeignKey) and/or prefetch_related (For ManyToMany or ManyToOne) so that it will not hit the database for each Model_B object.
If user is a FK in Model_B then you can do:
class ReportAPI(APIView):
def get(self, request):
all_projects = Model_B.objects.all().select_related('user')
project_serializer = SerializerB(all_projects, many=True)
return Response(project_serializer.data)
If the user model has other FK that you need in it's serializer, then you can also do select_related('user', 'user__other_field').

Related

MotorEngine - How to represent the equivalent of the foreign key in model?

In MongoDB I have a document that represents a Balance which has an Stakeholder's ID as a field.
I need to relate these two classes, Balance and Stakeholder, but I don't know what's the proper way. I've seen there's a field that could be appropiate but I still don't understand it: EmbeddedDocumentField()
class Balance(Document):
id = UUIDField()
creation_date = DateTimeField(auto_now_on_insert=True)
gross_balance = FloatField(required=True, min_value=0, default=0)
balances_description = StringField(required=True, max_length=255)
stake_holder = #FK to Stakeholder
class Stakeholder(Document):
...
Any idea?
If Stakeholder represents document from other collection and stake_holder is ObjectId, you should use ReferenceField()
stake_holder = ReferenceField(reference_document_type=Stakeholder)

Play, Scala, Ebean: Checking if relationship exists

Consider a hypothetical situation where I have two models: Company and User, defined like so
case class Company(name: String) extends Model {
#Id
var id: Long = _
#OneToMany(fetch = FetchType.LAZY)
var admins: util.List[User] = new util.ArrayList[User]()
}
case class User(email: String) {
#Id
var id: Long = _
}
Next, I have a request coming in and I want to check if user_id 200 is an admin of a company_id 100. The obvious solution is to fetch the company with that id, and then check iteratively in the admins list if a user_id but that is quite inefficient. What's the best way to go about this?
I think that the easiest way to solve this problem is to simply add relation from user to company. If you need calling such query then such relation has sense:
Here is relation added to User class:
#ManyToOne
var company:Company = _
And here is example how to check if user(id=200) is admin of company(id=100):
val user = Ebean.find(classOf[User], 200L)
println(user.company.id==100L)
Second option here is using RawSql. We can do it in a way similar to this:
val sql="select u.company_id as id from user u where u.id=200"
val rawSql = RawSqlBuilder.parse(sql).create()
val query = Ebean.find(classOf[Company])
query.setRawSql(rawSql)
val list = query.findList()
println(list(0).id==100L)

Getting from ToManyField to Model values

In django, I have two models - User and UserProfile. There may exist zero or one profiles for a particular user. I'm trying to include the information from the UserProfile model directly on the UserResource.
I would like to use the profile ToManyField, if it exists, to access the contents of the associated UserProfile model. I've tried a variety of things in dehydrate, including self.profile.get_related_resource(self) and UserProfile.objects.get(id=...), but I can't seem to find my way from the profile field to the model object. Can anybody help me out?
I'm still new to Python, Django, and Tastypie, so hopefully if I'm doing anything awful somebody will be kind enough to point it out.
The goal is to have JSON that looks like this:
{
resourceUri: /v1/users/1
date_of_birth: Jan 1, 1980
... etc
}
where date_of_birth is a property of the UserProfileResource. I don't want all of the fields from UserProfileResource, and I don't want the UserProfile to be a nested object in the response - I want some fields from UserProfileResource to be top-level fields in the response, so that they look like part of the User resource.
class UserResource(ModelResource):
profile = fields.ToOneField('foo.api.UserProfileResource', 'user', null=True)
class Meta:
queryset = User.objects.all()
resource_name = 'users'
allowed_methods = ['get']
#etc...
class UserProfileResource(ModelResource):
date_of_birth = ...
#etc
I assume you're using Django 1.4 and AUTH_PROFILE_MODULE?
Since the User:UserProfile relationship is 1:1 I would opt for the ToOneField instead. This will serialize as a URI pointer to your UserProfileResource (if one exists.) If you'd like the UserProfileResource field data inline with your UserResource, you can specify full=True in the ToOneField definition. With this method you should not need to override dehydrate.
Also, ensure that the second argument in the ToOneField definition is the User attribute which points to your UserProfile Django model. For example if you have OneToOneField(User, related_name='profile') in your Django model then this attribute should be profile.
class UserResource(ModelResource):
profile = fields.ToOneField('foo.api.UserProfileResource', 'profile',
full=True, null=True)
class Meta:
queryset = User.objects.all()
resource_name = 'users'
allowed_methods = ['get']
If what you're after are specific fields from the UserProfile instance mixed in with your User, you should be able to do something like this:
class UserResource(ModelResource):
date_of_birth = fields.DateField('profile__date_of_birth', null=True)
class Meta:
queryset = User.objects.all()
resource_name = 'users'
allowed_methods = ['get']
fields = ['userfields', 'gohere', 'date_of_birth']

Many to Many relation in JPA entities

I have 5 tables:
User:
username (PK)
Role:
role_id(PK)
role_name
Permissions:
perm_id(PK)
perm_name
User_role_rels:
ur_id(PK)
username(FK) -> user.username
role_id(FK) -> role.role_id
Role_perm_rels:
rp_id(PK)
role_id(FK) -> role.role_id
perm_id(FK) -> Permissions.perm_id
When I create JPA entities for these five tables I get List of UserRoleRels in User entity, but I would need list of permissions for this user. So, there should be a
List permList in User entity.
I am new to JPA and not sure how I can achieve this using annotations?
Since there is no direct relationship between User and Permission, it's correct that User doesn't have a permList collection property.
Assuming that your IDE has created correctly the entities according to your tables, you don't have ManyToMany annotations in your classes, but only OneToMany and ManyToOne. This makes a little cumbersome to fetch the permissions collection:
String userName = "";
User myUser = entityManager.find(User.class, userName);
for (UserRoleRels urr : myUser.getUserRoleRelsList()) {
Role r = urr.getRole();
for(RolePermRels rpr : r.getRolePermRelsList()) {
Permission p = rpr.getPermission();
}
}
If you don't have an extra property in the ManyToMany relation tables (in your case User_role_rels and Role_perm_rels), you can drop the PK field for both. This will let your IDE: (1) create simpler Entity classes, (2) avoid the creation of the Entity classes for the relation tables, (3) use the ManyToMany annotations. With that change, you'll be able to access the permissions more easily and in a more readable way:
String userName = "";
User myUser = entityManager.find(User.class, userName);
for (Role r : myUser.getRoleList()) {
List<Permission> pl = r.getPermissionList();
}
Useful links: EclipseLink UserGuide, JPA Wikibooks.

Entity Framework - How to Set Association Value?

Let's say I have a Person class and an Order class, with foreign keys in the DB. The EF model will mark Person with a List of Orders and Order with a Person instance.
If I want to set the Person for the Order, do I really have to do it with an instance of Person?
Is there not a slimmed down way to do so, say with just a PersonID ?
To assign Person entity to a Order without loading Person entity, you have to do something like this:
var db = new OneToManyEntities();
var Order = new Order { OrderId = 100, OrderName = "Order name" };
Order. PersonReference.EntityKey = new EntityKey("OneToManyEntities.Person ","PersonID",10);
db.AddToOrders(Order);
db.SaveChanges();
Puzzled's answer is correct for EF v1. It's a pain. If you don't mind the extra query, you can set the property succinctly:
int id = 1;
Order.Person = context.Persons.Where(x => x.PersonID == id).FirstOrDefault();
Entity Framework v4 will have "FK Associations", which is a fancy term for directly-settable foreign keys.