contentful / vault

Easy persistence of Contentful data for Android over SQLite.
https://contentful.github.io/vault/
Apache License 2.0
85 stars 19 forks source link

How do I query posts by a particular author, containing a particular tag and within a date range ? #111

Closed ishandutta2007 closed 8 years ago

ishandutta2007 commented 8 years ago

I am working with the blog app https://github.com/contentful/blog-app-android I want query posts by author and within a date range. I don't see those kinds of examples in sample given here https://github.com/contentful/vault#queries. Can someone help ?

mariobodemann commented 8 years ago

Hey,

you could try combining several where queries with each other: (this uses cat sample space: cfexampleapi, token: b4c0n73n7fu1)

List<Cat> all = vault.fetch(Cat.class)
    .where(Cat$Fields.NAME + " != ? " +
            "AND cast(strftime('%s', " + Cat$Fields.UPDATED_AT + ") as int) >= ? " +
            "AND cast(strftime('%s', " + Cat$Fields.UPDATED_AT + ") as int) <= ? "
        , "Nyan Cat",
        "1379000000",
        "1400000000")
    .all();

(Using sqlite to do the date comparisons)

Alternatively, you could try filtering them by hand, aka not let sqlite do the filtering, but you run through all the results by hand.

I hope this helps.

ishandutta2007 commented 8 years ago

Yes as you said it can be done at three places 1) while syncing data from cloud. 2) while querying from db. 3) filtering everything by hand in Java. But here is a thing, for me performance is the primary priority. Let me give you some numbers; I have use cases where I will have 20000 entries published on contentful of which only 100-150 will be result of a query. I am not sure if it is even feasible to sync every time 20k records to the app(android/ios). So ideally I need to filter out data before it reaches sqlite db , something around your sync() method that vault uses ? I haven't done maths around performance numbers and memory estimates yet. Maybe if you have data around these as well it would be useful.

mariobodemann commented 8 years ago

Hey,

the beauty about syncing, is that after the initial sync, only changed/added items will be retrieved and entered in vault. Since you are on a mobile app, I would recommend trying to download a big chunk of data and then process it locally, to not have the radio to be turned on for too long, and drain the battery this way, see DevBytes about networking.

Despite the networking, I would try taking a look in building a complex where statement, representing what you need to query for, harnessing the processing power of SQL.

If you want to hook in before the sync, you could completely avoid using Vault, by fetching specific data from Contentful, and saving them your self, maybe in SQLite, or maybe even in a different storage.

Sadly I cannot provide data about the memory and performance impact will be, because its highly dependant on your use case...

Greetings, Mario

ishandutta2007 commented 8 years ago

Well actually all 20k entries are susceptible to change, Initial design I was thinking of is to store the dynamic fields in contentful as well so that I don't have to join anywhere. For example you may have ecommerce apps where they need to track number of items in stock, storing such dynamic fields in contentful is neither a good idea due to re-syncing issue nor is it easily achievable for contentful not giving any write APIs. I can have a DB/MBAAS on cloud where i track these counters, but I don't want to join it with contentful data on device for scalable reason. (the joining should havven on cloud).Do you have any idea how do your customers implement these ?

mariobodemann commented 8 years ago

Hey,

interesting problem. For dynamic data using Contentful you might be running into a rate limit problem: More then 10 people buying at the same time might be hitting the limits on us. Also you will run into concurrency issues: How do you avoid having two clients remove the same item at the same time?

My suggestion is to use Contentful to store less dynamic data of the product, like name, description, photos, reviews, etc., and use a third party solution for highly dynamic data, like redis, firebase, etc, mapping Contentful entry Ids to number of items available. This way you can have the offline sync of the less dynamic data, and can do a separate request to the other endpoint, if the user wants to take a look at buying it.

You could also have a webhook on the thirdparty, to write to contentful, once an item goes out of stock, changing one field in Contentful, to be able to update the availability on the client. Combining this with a silent push message (a tickle) on the android client, will almost serve as a dynamic work around.

You are able to write to Contentful using the management api for java, but I am not sure if this scales for updating the amount of available items.

Mario

mariobodemann commented 8 years ago

Closing this issue, due to inactivity.