javascriptcouchdbcouchdb-2.0fauxtonnosql

Get value from database into different database


I'm working on a CouchDB use case where I have 3 databases, where I have customers, invoices (which includes an array of invoiceLines) and items. In the invoiceLines array, I currently have this

       "_id": "someId",
      "_rev": "someId",
      "invoiceId": 46,
      "invoiceDate": "11/24/2016",
      "customerId": 85,
      "invoiceLines": [
       {
        "quantity": 10,
        "totalPrice": null,
        "itemId ": 53
       },
       {
        "quantity": 8,
        "totalPrice": null,
        "itemId ": 33
       } 
] } }

Then I want to take the price from my items db and put into the totalPrice value, where it's currently null. Is there an option to take the itemPrice from itemId in the items db?

 {
  "_id": "someID",
  "_rev": "someRev",
  "itemId": 1,
  "itemName": "gravida",
  "itemPrice": "$39.05"
  }

Hope someone can help and I'm sorry if it's a simple question, but I'm still new to CouchDB and NoSQL.


Solution

  • As for your problem, you can't really use reduce function to get the total price (as you will do with joins in SQL).

    What I suggest you to do is the following :

    1. Build a view that emits a complex key like this [invoiceId,{_id:itemId}]
    2. The view that you just build would also emit the actual invoice for the following key : [invoiceId, null]. This way, you get all your informations in one query.
    3. You query your with with your invoiceId and you locally compute the totalprice. This way, if you update the price of a single item, the totalprice will be updated.

    Full example:

    Invoice template :

    {
      "_id": "306860e48b2f6f668c7f409f33000339",
      "_rev": "3-73197f590a5d18b2ee01ebc423cacbb6",
      "type": "invoice",
      "invoiceDate": "11/24/2016",
      "customerId": "customer_1",
      "invoiceLines": [
        {
          "quantity": 10,
          "item": "item_1"
        },
        {
          "quantity": 8,
          "item": "item_2"
        }
      ]
    }
    

    Item template

    {
      "_id": "item_1",
      "_rev": "2-879798bd718975fe9957a2a699e041d0",
      "type": "item",
      "name": "First item",
      "price": 1
    }
    

    View function

    function(doc){
        if(doc.type == "invoice"){
            emit([doc._id]);
            if(doc.invoiceLines){
                for(var n in doc.invoiceLines){
                    var line = doc.invoiceLines[n];
                    emit([doc._id,line.item],{_id:line.item});
                }
            }
        }
    }
    

    Now what should you do?

    1. Query the view with those parameters ?key=invoiceId&include_docs=true&group_level=1
    2. Iterates through your data and create a map from the items and assign your invoice to a variable.
    3. Now in your invoice, for each items, set the total price by multiplying the quantity with the item price.

    Other solution

    Another way to do it (simplier but in two request) 1. Request the invoice document 2. Request the items with the ids from the invoice document. 3. Compute the total price

    Also, you could do this:

    When you create an invoice, you could link the item id and compute the total price of the item while creating the document. As it's an invoice, we don't care if the price is updated in the future as it's an invoice (correct me if I'm wrong).