Something like relations

relation
relationship
index
secondary

#1

I should make a site price comparisons in pure aerospike, then: products, combination products (a cpu related with some motherboards) stores. The products should relate with the stores, for example a product is related to three stores and each store has a different price.

Aerospike can help me in this?

I thought I might make the relationship bins, but I do not know if it is a good idea suggestions to solve the problem?


#2

Aerospike is a key-value store with no support for relations. If you have lots of relational data then you should probably use a relational database, otherwise there’s going to be lots of work to maintain all these relationships yourself in code.


#3

Ok, Understand…Thank you!


#4

Hi mdwalter, I will reach out to directly to help you with a way to build out the model and then augment the model to have the best query responses to your data set.

Given the NoSQL nature, ‘manigandham’ is right: it does not come out of the box, but it’s nonetheless doable and there are many tricks that can be applied to actually make this work well for the types of use cases that you would like to subject this to.

Thx s


#5

Really thank you for answer me! I know for one to many I can use ldt, list, map and ok. But for many to many I not understand how. I have this sets: Products(secondary index), stores(secondary index) and products_stores, in last one I put secondary index from products and stores, the bins name is products_id and stores_id and in this bin I copy secondary index? Or I need something totally different? Can you give me an example of how I should structure the DB and how should I run the query? I’m sorry for my english I know is not good…Thank again!


#6

Might be too late but here is an example how any key-value store supports relations:

You have products that are available in a few stores and each store can have many products in their shelves. To support something like this in NoSQL you would typically NOT create a new structure/record to save the relations but extend the existing records for both Product_xxx as well as Store_xxx (representing a single Store or Product each).

Product_xxx {
    ...
    "available_in_stores": ["Store_1", "Store_55", "..."]
}

and the other way around:

Store_xxx {
    ...
    // Depending on the amount of products, use an Large ordered-List (LDT) or normal array.
    "products": ["Product_44", "Product_19", "Product_1994", ".."]
}

This allows to answer the following queries:

  • What stores sell a given product
  • What products are sold in a given store

You can fully support relations in your data scheme - it’s just that with NoSQL it’s your own duty to think about it’s implementation to the end and e.g. come up with a concept of updating these relations (e.g. in this case one needs to update the Store_xxx.products at the same time as updating the Product_xxx.available_in_stores-List. This is why you have to write in multiple places when updating such a model while reading is relatively comfortable (and real time!). This process of keeping redundant information to support real time querien is called de-normalization.

Hope this helps anybody stumbling to this thread.


#7

Thank you for answer me, now I understand that is possibile create a relations, so how I use bin/ldt for create relation? I like this Db because is very fast, but thi si s new for me :smile:


#8

As Manuel said, you really need to model your data to solve your particular scenarios, that is what your use-cases are asking you to do. This often results in de-normalization of data but the exact de-normalization of the data is application specific.

For example, if your use-case required you to be able to determine the quantities of a particular product in a particular store, you might have one Set which has a compound key containing the storeId and productId with a Bin holding the inventory count in that store. This would make it a very fast lookup.

However, if you want to know which stores have particular products, and which products are in which stores, you might model it closer to how Manuel says. With NoSQL databases, it’s best to approach your modeling from the use-case perspective rather than “how do I form a general data model to store my information, I’ll work out how to address the use cases later”.

If you want to model the information along the lines Manuel has suggested, this is a little code snippet (using the Java client) which might help:

// Create a new store, and give it a couple of products
List<String> productIds = Arrays.asList("prod1234", "prod1235");
String storeId = "store00314";
Bin name = new Bin("name", "a Store");
Bin products = new Bin("productIds", productIds);
Key storeKey = new Key("test", "store", storeId);
client.put(null, storeKey, name, products );
		
// The store now contains the products, we have to make sure we tell the products
// that they're in the store too. Note the use of the generationPolicy to make sure
// we don't bump into concurrency issues.
for (String productId : productIds) {
    Key productKey = new Key("test", "product", productId);
    Record thisProduct = client.get(null, productKey);
    List<String> storeIds = (List<String>) thisProduct.getValue("stores");
    if (!storeIds.contains(storeId)) {
        // We have to add it back into this list
        storeIds.add(storeId);
        // And put it back, ensuring it hasn't been changed in the meantime
       WritePolicy writePolicy = new WritePolicy();
       writePolicy.generation = thisProduct.generation;
       writePolicy.generationPolicy = GenerationPolicy.EXPECT_GEN_EQUAL;
       client.put(writePolicy, productKey, new Bin("stores", storeIds));
    }
}

Now we can use the query operations to find out information about the products:

// Now see if a given product is in the store
String prodId = "prod1235";
Key theStoreKey = new Key("test", "store", storeId);
// Get the products for the store, in this case this is the only information we want so
// just specify the one bin name.
Record storeRecord = client.get(null, theStoreKey, "productIds");
List<String> storeProductIds = (List<String>) storeRecord.getValue("productIds");
if (storeProductIds.contains(prodId)) {
    System.out.println("Store contains product!");
}

Note that I’m using a list here rather than a large list. If you’re storing ids, a list is probably fine for your needs – you have up to 128kB to play with in a single Record and this is expandable if needed so shouldn’t be a limitation. A Map here would probably work better too, but I’m not sure of your particular use case so I thought the list example might be simpler. If your lists are growing very large you might have a processing impact as you search through them which could be solved by modeling the data differently – again this depends on your use-cases.

Hope this helps,

Tim


#9

Thank you!!! You gave me information precious!!!