1

I basically have 2 Parse classes in my Online Shop: Product and Order. While the user fills his shopping cart, I reflect that in a local array of items (javascript object) with a property for the product (parse class) and another property for the amount that particular product should have in the cart.

If I now save the order to parse (I'm using the self hosted open source version of parse-server), I end up with an order object like this:

{
  "_id": "8XK6gbZZvE",
  "items": [
    {
      "amount": 3,
      "product": {
        "__type": "Pointer",
        "className": "Product",
        "objectId": "VWOxzFui6R"
      }
    }
  ],
  "total": 1800,
  "status": "pending",
  ...
}

My problem with that is that I couldn't find a way to query for orders where the result already includes the products.

The only way I currently can think of is to get rid of the amount so that I don't have to nest the product class inside a JS object. And then just add a product multiple times to the array if necessary.

Something like that:

{
  "_id": "6j7l5acSB3",
  "items": [
    {
      "__type": "Pointer",
      "className": "Product",
      "objectId": "VWOxzFui6R"
    }
  ],
  "total": 1210,
  "status": "processing",
  ...
}

Which then allows me to include the items in the order query like this query.include('items');

But would there be also a solution how I could use a structure like my first one and still be able to include the products in the order query? It kind of feels "redundant" to have the same product multiple times in an array if the user ordered this product e.g. 2 or 3 times.

1 Answer 1

1

The way this is done in most ecommerce systems is to have another object that adds data to the relationship between order and product, for example...

// Order
{ lineItems: [ <pointer to line item>, < etc > ],
  orderTotal: number,
  // other fields: probably a customer-pointer, tax, shipping, etc
};

// Line Item - this is the missing concept in the OP
{ product: <pointer to product>,
  unitPrice: number,
  quantity: number
};

// Product as you have it

Notice that the unitPrice is probably redundant with a price attribute kept with product. The app would copy the product price to this field when the product is added to the order. This enables a business logic decision abut what to do if the product price changes after the order is created.

The order query can include('lineItems', 'lineItems.product')

Sign up to request clarification or add additional context in comments.

6 Comments

So what you suggested would require a new DB Collection called "line_items", right? Especially because you pointed out that product prices might change, this definitely makes sense. I just tested what you suggested using pointers and it works. I'm just not sure wether it'd be better to use join tables for that.
Yes. Suggesting a new LineItem collection. It is a join between order and product.
Yes, technically this new LineItem collection acts as a join but parse is offering a dedicated join functionality to create those joins (see: link) but I'm still not convinced to use this specific join functionality over your proposed pointer solution.
Do you mean on which side of the relation to put the pointer between order and line item? Its tough without understanding more about the app, but remember that if you have the pointer on the LineItem side, you're probably doing a second query to get from order to line item. (find line items where order equalTo someOrder). I like the singular pointer on the "belongs to" side, but the question seemed to be going for a single query. Also worth noting that a pure mongodb order would probably embed the line items in the order document (which might be relevant after parse.com shuts down)
Since I'm using the self hosted (open source) version of parse, I do not necessarily need to embed the line items in the order. So I think I'll just stick with the pointer on the order side for now. It feels like embedding the line_items in the order is something I could do anyways later if needed though. THX, your input helped a lot!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.