is it possible in Objectify to order by a field of a referenced object?
Example:
public class Foo {
#Id private long id;
#Index Ref<AnObject> ref;
}
public class AnObject {{
#Id private long id;
#Index name;
}
Then I try to do this query and it's not working:
Query<Foo> query = ofy().load().type(Foo.class)
.limit(Constants.DATASTORE_LIMIT)
.order("ref.name");
Thanks.
I'm afraid not. This is not something supported by the datastore. It can't do joins.
There are basically two ways around that limitation:
Denormalize and put an indexed copy of the 'name' data in your Foo object. You can do this somewhat automatically with an #OnSave method. The downside is that you need to remember to update the data in both places if it changes.
Do the work of the query planner yourself. Query for the relevant AnObjects, then query for the relevant Foos.
Related
What I'm trying to do is basically Entity A which have field type to relate with Entity B or C base on the value of field type
for example: a Product if is type drinks to be related with DrinkOptions entity, but if it's with type food to be related with FoodOptions entity
Is there any elegant solution which can work fine in such case?
This is what I thought it will work, but it doesn't..
Changing dynamically the entity A relation will not help, because it's not yet loaded and I can't see the value of field type
combine the different option entities into one, but it will be very ugly picture with 200+ properties..
define all option types in the config and then dynamically create the mapping with the loadClassMetadata, but is not so pretty also it requires a "dummy" property, getters and setters for all option types in the Entity A
A possible solutions could be to use a single table inheritance. Might not be the nicest solution but it could fit your specific need.
<?php
namespace MyProject\Model;
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discriminator", type="string")
* #DiscriminatorMap({"drink" = "DrinkOption", "food" = "FoodOption"})
*/
class Option
{
// ...
}
/**
* #Entity
*/
class FoodOption extends Option
{
// ...
}
/**
* #Entity
*/
class DrinkOption extends Option
{
// ...
}
You then could even switch the type by altering the "discriminator" column.
I think the simpliest way would be to have multiple product entities with an inheritence
Like Product (parent) -> foodProduct (child) or DrinkProduct().
This way you could have Product link to common others entities (like price or brand) and specific link for food, drinks, smokes etc...
Product
id:
type: food/drink/smoke etc..
foodproduct: one to Many nullable: FoodProduct (it's actually one to zero/one but i find it more performant)
drinkproduct: one to Many nullable: DrinkProduct
smokeproduct:one to Many nullable: SmokeProduct
FoodProduct:
id:
product_id (many to one to Product)
options one to many to foodOptions
If it still don't fit you will have to find some design pattern
I have created a list (dd) which contains instances of a class. I want to be able to perform queries on some of its attributes (eg. finding the smallest numeric value), but cannot find a way to do this using the functionality of the class (I feel like going back to analysing the data by column). How do I access the values in one of the attributes when my instances are now on a list? Thanks!
Assuming you're using C# and having a class like this
class Foo
{
public double Bar { get; set; }
}
then LINQ is exactly what you are looking for
List<Foo> list = GetList();
var filtered = list.Where(p => p.Bar > 23.0);
Have a look at these examples:
https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
I am defining an entity that just stores document objects for the user. Sometimes the object is a binary (BLOB) such as a PNG or JPG image, and sometimes it is character based, such as RTF text files or a MIME text/* type. All documents have a unique ID in the same name space. The properties are roughly like this:
#Id private long id;
#Column private String type;
#Lob private byte [] rawData;
Now I could just provide some accessor methods that would convert rawData from a byte [] to a String on demand, but is there a technique that avoids the frequent conversion step in the case of character data? Note that I don't want the JPA provider to do it either -- I want to use one table column to store either the character data or the binary data with minimal or no transcription overhead when it is injected into the entity instance.
I think I should be able to code a base class and two sub-classes like this:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
public class Document {
#Id private long id;
#Column private String type;
}
#Entity
#DiscriminatorValue("binary")
public class BinaryDocument extends Document {
#Column #Lob private byte [] binaryData;
}
#Entity
#DiscriminatorValue("text")
public class TextDocument extends Document {
#Column #Lob private String textData;
}
(omitted accessor methods for brevity)
If I understand this I would end up with a table with two #Lob columns, binaryData and textData. Is there any way to make them the same column?
Or should I care? Would the space requirement for having two columns (only one of which is used in each instance of the class) be minimal?
Or should I be taking a completely different approach? I am open to suggestion since I haven't spent much time on coding this yet.
I have an entity 'Order', and a one-to-many associated entity 'OrderStatus' (so 1 order can have many statuses). The current status of an order is defined by the last status that was added to that order.
Now I want to create a DQL query which selects all orders with a certain status. However, because this is a one-to-many relation, I have no idea how to accomplish this in DQL. I only know of querying the collection of statuses as a whole.
Does anyone have an idea if this is even possible, or do I have to use a workaround?
We had this very same problem in a project we're working on. The query you're trying to perform is very similar to this question, except that you're trying to do this in DQL, which makes it even harder. I think (but I might be wrong) that DQL does not allow this kind of query, and you may achieve the result you're expecting with a native SQL query, with all the caveats this implies.
What we ended up with, and I strongly suggest to you, is to make the current status a property of your Order. This allows easy & fast querying, with no joins required. The change is really painless:
class Order
{
/**
* #ManyToOne(targetEntity="OrderStatus")
*/
protected $status;
/**
* #OneToMany(targetEntity="OrderStatus")
*/
protected $statuses;
public function setStatus($status)
{
$orderStatus = new OrderStatus($this, $status);
$this->statuses->add($orderStatus);
$this->status = $orderStatus;
}
}
$status can also be a simple string property, if your OrderStatus is basically composed of a status string and a date; the code would then become:
class Order
{
/**
* #Column(type="string")
*/
protected $status;
// ...
public function setStatus($status)
{
// ...
$this->status = $status;
}
}
I have been trying to delete the inverse relationship on a JPA entity, however this have not been working well. What I'm trying right now is to set the ManyToOne property to null and then saving it using the entityManager's merge method. The ManyToOne relationship is marked with the cascade all property, however in the dataBase the foreign key is not removed. How should I do this?. Thanks a lot.
It would be easier to find out what you mean, with code in question. But I will try anyway:
#Entity
public class AEntity {
#GeneratedValue (strategy = GenerationType.SEQUENCE)
#Id int id;
//Having some cascade here doesn't matter for our case
//because we now do not cascade anything, we just set this field to
//null. Cascade=REMOVE is about never meaningful (and never fully
//fully portable) in ManyToOne side:
//just think what happens to other AEntity instances that refer to
//same BEntity.
#ManyToOne
BEntity bEntity;
public void setbEntity(BEntity bEntity) {
this.bEntity = bEntity;
}
}
public class BEntity {
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Id int id;
}
In the beginning we have following data:
AEntity(id=1,bEntity_id=2)
BEntity(id=2)
Then removing connection between a and b:
AEntity oldDirty = em.find(AEntity.class, 1);
//modify A somewhere else in code
oldDirty.setbEntity(null);
//and bring changes in:
em.merge(oldDirty);
Afterwards we have:
AEntity(id=1,bEntity_id=null)
BEntity(id=2)
If BEntity also have set that contains AEntity entities (so to say bidirectional relationship), then you have to remove A from there as well, because you have to keep care about relationship by yourself. OneToMany side is one where it can make sense to cascade removal from.
Check the cascade type of the relationship on both ends. For instance, if you want to delete all the associated entities when you delete the main entity, the annotation should look like this: #ManyToOne(cascade={CascadeType.REMOVE}), and on the inverse #OneToMany(cascade={CascadeType.REMOVE})