yasar
yasar

Reputation: 13748

Searching a many to many database using Google Cloud Datastore

I am quite new to google app engine. I know google datastore is not sql, but I am trying to get many to many relationship behaviour in it. As you can see below, I have Gif entities and Tag entities. I want my application to search Gif entities by related tag. Here is what I have done;

class Gif(ndb.Model):
    author = ndb.UserProperty()
    link = ndb.StringProperty(indexed=False)

class Tag(ndb.Model):
    name = ndb.StringProperty()

class TagGifPair(ndb.Model):
    tag_id = ndb.IntegerProperty()
    gif_id = ndb.IntegerProperty()

    @classmethod
    def search_gif_by_tag(cls, tag_name)
        query = cls.query(name=tag_name)
        # I am stuck here ...

Is this a correct start to do this? If so, how can I finish it. If not, how to do it?

Upvotes: 1

Views: 211

Answers (3)

dragonx
dragonx

Reputation: 15143

There's different ways of doing many-to-many relationships. Using ListProperties is one way. The limitation to keep in mind if using ListProperties is that there's a limit to the number of indexes per entity, and a limit to the total entity size. This means that there's a limit to the number of entities in the list (depending on whether you hit the index count or entity size first). See the bottom of this page: https://developers.google.com/appengine/docs/python/datastore/overview

If you believe the number of references will work within this limit, this is a good way to go. Considering that you're not going to have thousands of admins for a Page, this is probably the right way.

The other way is to have an intermediate entity that has reference properties to both sides of your many-to-many. This method will let you scale much higher, but because of all the extra entity writes and reads, this is much more expensive.

Upvotes: 0

marcadian
marcadian

Reputation: 2618

Maybe you want to use list? I would do something like this if you only need to search gif by tags. I'm using db since I'm not familiar with ndb.

class Gif(db.Model):
    author = db.UserProperty()
    link = db.StringProperty(indexed=False)
    tags = db.StringListProperty(indexed=True)

Query like this

Gif.all().filter('tags =', tag).fetch(1000)

Upvotes: 0

Faisal
Faisal

Reputation: 2276

You can use repeated properties https://developers.google.com/appengine/docs/python/ndb/properties#repeated the sample in the link uses tags with entity as sample but for your exact use case will be like:

class Gif(ndb.Model):
    author = ndb.UserProperty()
    link = ndb.StringProperty(indexed=False)
    # you store array of tag keys here you can also just make this
    # StringProperty(repeated=True)
    tag = ndb.KeyProperty(repeated=True)

    @classmethod
    def get_by_tag(cls, tag_name):
        # a query to a repeated property works the same as if it was a single value
        return cls.query(cls.tag == ndb.Key(Tag, tag_name)).fetch()

# we will put the tag_name as its key.id()
# you only really need this if you wanna keep records of your tags
# you can simply keep the tags as string too
class Tag(ndb.Model):
    gif_count = ndb.IntegerProperty(indexed=False)

Upvotes: 2

Related Questions