Queries with JDOQL Unique Result Set - google-app-engine

In my GAE application I want to make a JDOQL which returns a List where every element exist at most once even in the database there are more. How can I do this?

I dont know about JDOQL, but if you want a list where each entity exists utmost once i.e each list element is unique, then you could do the following:
Asume you have an entit type / model class that we call Type, with attributes att1,attr2.
You want to have a list of unique elements based on one or more of the attributes, say attr2.
you can use the following method that I adapted from a good source on the issue:
def unique(seq, idfun=None):
''' A function that returns a list of unique items in a very efficient manner
Refer to : http://www.peterbe.com/plog/uniqifiers-benchmark '''
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
the to get a list of unique elements from the datastore type Type based on attr2 i could do something like:
list = Type.all()
unique_list = unique(list,lambda t: t.attr2)
Hope this helps because it has been the best method for me so far.

Related

Rails update remove number from an array attribute?

Is there a way to remove a number from an attibute array in an update? For example, if I want to update all of an alchy's booze stashes if he runs out of a particular type of booze:
Alchy has_many :stashes
Stash.available_booze_types = [] (filled with booze.ids)
Booze is also a class
#booze.id = 7
if #booze.is_all_gone
#alchy.stashes.update(available_booze_types: "remove #booze.id")
end
update: #booze.id may or may not be present in the available_booze_types array
... so if #booze.id was in any of the Alchy.stash instances (in the available_booze_types attribute array), it would be removed.
I think you can do what you want in the following way:
if #booze.is_all_gone
#alchy.stashes.each do |stash|
stash.available_booze_types.delete(#booze.id)
end
end
However, it looks to me like there are better ways to do what you are trying to do. Rails gives you something like that array by using relations. Also, the data in the array will be lost if you reset the app (if as I understand available_booze_types is an attribute which is not stored in a database). If your application is correctly set up (an stash has many boozes), an scope like the following in Stash class seems to me like the correct approach:
scope :available_boozes, -> { joins(:boozes).where("number > ?", 0) }
You can use it in the following way:
#alchy.stashes.available_boozes
which would only return the ones that are available.

Neo4j - Array inside an array inside a relationship

For a few days now, I've been designing a social network database structure and I've been optimizing over and over again the data structures.
What I am trying to achieve in Neo4j:
I am trying to create a relationship between two nodes which has a property called "history" and one called "currentStatus". The problem is that both are (should be) arrays. Something like:
MATCH (u:User {username: 'john.snow#gmail.com'}), (uu:User {username: 'sansa.stark#gmail.com'})
MERGE u-[rel:FRIENDSHIP]->uu
ON CREATE SET rel.previousFriendshipUpdates = [], rel.currentFriendshipStatus = [sentTime: timestamp(), status: '0']
ON MATCH SET rel.previousFriendshipUpdates = [rel.previousFriendshipUpdates + rel.currentFriendshipStatus], rel.currentFriendshipStatus = [sentTime: timestamp(), status: '1']
I want to keep a history of whatever actions regarding they're friendship take place (sender sent friend request at x time, receiver rejected friend request at x time, sender sent friend request (again) at x time, receiver accepted at x time, receiver unfriended sender at x time, etc).
Thank you in advance.
To add values to array (collection) property arr on relationship r you can do
SET r.arr = r.arr + 'newvalue'
or
SET r.arr = r.arr + ['onevalue', 'nothervalue']
(see How to push values to property array Cypher-Neo4j)
But arrays cannot contain values like sentTime: timestamp(). That looks like a property and an array can't have properties.
Nodes can have properties, however, and both the structure of your example query and the description of your model suggests that you represent the friendship as a node instead. Let each :Friendship node have [:MEMBER] relationships to two :User nodes. Then keep the friendship status as a property on that node. A good way to model relationship history could be to create a node for each update and keep these in a "linked list" that extends from the :Friendship node.

Logical-Indexing for Matlab-object-arrays

Is there any way in Matlab R2011b to apply logical-indexing to object-arrays? The objects which fulfill specific condition(s) regarding their properties should be returned. At best the solution is also possible with object-arrays that are a property of another object (aggregation).
In my project there are a lot of entities which have to be identified by their manifold features. Matlab objects with their properties provide a clear data foundation for this purpose. The alternative of using structs (or cells) and arrays of indices seems to be too confusing. Unfortunately the access to the properties of objects is a little bit complicated.
For Example, all Objects in myArray with Element.val==3 should be returned:
elementsValIsThree = myElements(Element.val==3);
Best solution so far:
find([myElements.val]==3);
But this doesn't return the objects and not the absolute index if a subset of myElements is input.
Another attempt returns only the first Element and needs constant properties:
myElements(Element.val==3);
A minimal example with class definition etc. for clarification:
% element.m
classdef Element
properties
val
end
methods
function obj = Element(value)
if nargin > 0 % to allow empty construction
obj.val = value;
end
end
end
end
Create array of Element-Objects:
myElements(4) = Element(3)
Now myElements(4) has val=3.
I'm not sure I understood the question, but the logical index can be generated as
arrayfun(#(e) isequal(e.val,3), myElements);
So, to pick the elements of myElements whose val field equals 3:
elementsValIsThree = myElements(arrayfun(#(e) isequal(e.val,3), myElements));

HOW to sort db.ReferenceProperty property?

I have two kind like this:
class A(db.Model):
propertyA = db.XxxProperty(required=True)
class B(db.Model):
reference = db.ReferenceProperty(A,collection_name="Bs",required=True)
date = db.DateTimeProperty(auto_now_add=True)
Now I want make A.Bs has order, you konw, means using B.date to order A.Bs.
How can I do that? What GQL query should I write?
Thank you!
Try this
a.Bs.order("date")
or (for descending order):
a.Bs.order("-date")
Shay's suggestion is succinct and correct, though I think it would be helpful to add some more detail.
Using the same two class examples as in the question, I created the following class for rendering my page (GAE, python, jinja2)
class MainPage(Handler):
def get(self):
a_id = '1001' # magically get id of target entity a somehow
# get key using a_id, then retrieve entity using that
a = db.get(db.Key.from_path('A', a_id, parent=reg_key()))
# look up the collection and assign it to b
b = a.Bs
# sort items in collection in reverse
b.order('-created')
# pass b to the template to get rendered (I use a custom method in my Handler)
self.render('main.html', b = b)

Python - read with key in App Engine

I have a python program in Google App Engine
When finding an object in the datastore when I have the key as a string, how can I do a direct read. Below is my code which is performing a loop, not good.....
class Opportunity(db.Model):
customer = db.ReferenceProperty(Customer,collection_name='opportunitys')
BNusername = db.StringProperty()
opportunity_no = db.StringProperty()
# etc etc etc.....
#BnPresets holds the object key as a string
opportunitys = Opportunity.all()
opportunitys.filter('BNusername =',BnPresets.myusername)
for oprec in opportunitys:
if str(oprec.key()) == BnPresets.recordkey:
opportunity = oprec
# I have the object here and can process etc etc
You can instantiate db.Key from string by passing it directly to the constructor:
opportunity_key = db.Key(BnPresets.recordkey)
Once you have that, simply db.get to obtain the entity identified by this key:
opportunity = db.get(opportunity_key)
I guess (by looking at the query you use) that you also want to verify the username of the object you got:
if opportunity.BNusername == BnPresets.myusername
process_opportunity(opportunity)
That should be pretty much it. The bottom line is that you should use the key first - as it uniquely identifies your entity - rather than querying for some other property and iterating through results.

Resources