0

I need best practice tips to enhance the performance of my noSQL database (hosted on Firebase). Moreover, I need tips on how to structure the nodes.

The database stores product information, with three main properties:

$productId          
     /date           
     /category           
     /subcategory

On my website, I have three views:

  • retrieve the last 4 products (orderBy date)
  • retrieve last 4 products (by date) of category X
  • retrieve last 4 products (by date) of category X and subcategory Y.

Note that I also have a node product_images, which have subnodes matching the productIDs. So constructing the databas as follows:

$categoryId
        $subCategoryId 
               $productId

will not work as I need to know beforehand the $categoryId and $subCatrgoryId before I can match it with $productId. It would also make it difficult to retrieve the last 4 products.

How would I construct my noSQL database in an efficient way, and how would I retrieve the products with Firebase filtering it out with multiple restrictions?

I know that in Firebase you can use orderByChild and equalTo, but this only works on one restriction, whereas I have to deal with one to three.

Community
  • 1
  • 1
WJA
  • 6,676
  • 16
  • 85
  • 152

1 Answers1

5

Since Firebase only can filter on one property, you'll have to combine the values you want to filter on into a single property. Since you have multiple filtering needs, you might need such a property for each filtering use-case.

It seems that this will be possible for you if you combine <category>_<date> into a single property, which we'll call multi-prop. We'll also combine <category>_<subcategory>_<date> into a property called megaprop:

$productId          
    /date           
    /category           
    /subcategory
    /multiprop
    /megaprop

Some sample data:

id_cc_1234
    date: 20151031
    category: candy
    subcategory: halloween
    multiprop: candy_20151031
    megaprop: candy_halloween_20151031
id_tg_2345
    date: 20151125
    category: candy
    subcategory: thanksgiving
    multiprop: candy_20151125
    megaprop: candy_thanksgiving_20151125
id_tg_3456
    date: 20151125
    category: food
    subcategory: thanksgiving
    multiprop: food_20151125
    megaprop: food_thanksgiving_20151125
id_sk_4567
    date: 20151205
    category: candy
    subcategory: sinterklaas
    multiprop: candy_20151205
    megaprop: candy_sinterklaas_20151205
id_sc_5678
    date: 20151225
    category: candy
    subcategory: christmas
    multiprop: candy_20151225
    megaprop: candy_christmas_20151225

Now your queries turn into:

  1. retrieve the last 4 products

    ref.orderByChild('date').limitToLast(4);
    
  2. retrieve last 4 products of category X

    ref.orderByChild('multiprop').startAt('candy').endAt('candy_~').limitToLast(4);
    
  3. retrieve last 4 products of category X and subcategory Y.

    ref.orderByChild('megaprop').startAt('candy_christmas').endAt('candy_christmas_~').limitToLast(4);
    

Also see: http://jsbin.com/piluzo/edit?js,console for a working version.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Makes definitely sense! Just to add, lets say I have 10000 products and 20 categorirs. I am quering the categories on 1 view. Will it be slower if I query 20 times on the node products compared to one time for each category, thus on products/$categoryId? – WJA Oct 26 '15 at 08:07
  • Just tried it, this is not working unfortunately. It takes out all the products that start with candy, instead of only candy_christmas – WJA Oct 26 '15 at 10:28
  • 3
    This answer is correct, and there are several other options depending on your platform. We have found that querying all Candy and putting the results into an Array and then (ObjC) NSPredicate to 'filter' the data we want (christmas) out of that array works well (depending on dataset size). Also, structuring your data differently; have a christmas_candy node and a thanksgiving_candy node where their children contain refs to the corresponding children in the main candy node. This gives you access to an 'array' that could be iterated over to retrieve the data you want from the main candy node. – Jay Oct 26 '15 at 18:34