node-odata
node-odata copied to clipboard
query the example of 'complex-resource'
I have tried to add some mock data for the complex-resource example, which has its structure as,
var order = {
custom: {
id: String,
name: String
},
orderItems: [{
quantity: Number,
product: {
id: String,
name: String,
price: Number
}
}]
};
The question is, how can I get the result that the orderItems have their products with the prices higher than 10.00, for example?
I have tried the queries like, without luck.
1. GET orders?$filter=price gt 10
2. GET orders?$filter=product/price gt 10
3. GET orders?$filter=orderItems/product/price gt 10
the results are always empty, was this a bug or something I was missing, any ideas?
{"value":[]}
The mock data:
{ "_id" : "fb107243-5f4d-4d47-8b35-245fa85127cd", "orderItems" : [ { "quantity" : 100, "_id" : ObjectId("57e303cdd70bda6419c9922d"), "product" : { "id" : "item123", "name" : "ITEMA", "price" : 10 } } ], "custom" : { "id" : "abc123", "name" : "ABC" } }
{ "_id" : "1c1ceeea-8c75-443e-8706-fa696ec5acf6", "orderItems" : [ { "quantity" : 200, "_id" : ObjectId("57e30426d70bda6419c9922e"), "product" : { "id" : "item234", "name" : "ITEMB", "price" : 15 } } ], "custom" : { "id" : "bcd123", "name" : "BCD" } }
{ "_id" : "a8dd0f23-46d9-4f6e-bffa-9709e7c23b87", "orderItems" : [ { "quantity" : 300, "_id" : ObjectId("57e30454d70bda6419c9922f"), "product" : { "id" : "item345", "name" : "ITEMC", "price" : 20 } } ], "custom" : { "id" : "efg123", "name" : "EFG" } }
{ "_id" : "316efd3f-0b30-4ad1-ac22-2640a613142e", "orderItems" : [ { "quantity" : 400, "_id" : ObjectId("57e30474d70bda6419c99230"), "product" : { "id" : "item456", "name" : "ITEMD", "price" : 30 } } ], "custom" : { "id" : "hij123", "name" : "HIJ" } }
Sorry, it's not support this feature, it can only support a simple model query. I will try to add it on this weekend.
Hi @TossShinHwa, many thanks for your quick reply!
It seems working well before I add following new orderItems to the collection,
{"orderItems":[{"quantity":1000,"product":{"id":"item777","name":"ITEM7","price":10}},{"quantity":2000,"product":{"id":"item888","name":"ITEM8","price":15}},{"quantity":3000,"product":{"id":"item999","name":"ITEM9","price":20}}],"custom":{"id":"xyz123","name":"XZY"}}
In this case, if I query,
GET orders?$filter=orderItems.product.price lt 15
The response would always include the entire array, if there is at least one price in the array matches the query. I wonder if I have to use $expand or any/all functions to further filter (refine) the result in this case?
The response of above query (price less than 15):
{"value":[{"orderItems":[{"quantity":100,"product":{"id":"item123","name":"ITEMA","price":10},"id":"57e303cdd70bda6419c9922d"}],"custom":{"id":"abc123","name":"ABC"},"id":"fb107243-5f4d-4d47-8b35-245fa85127cd"},**{"orderItems":[{"quantity":1000,"product":{"id":"item777","name":"ITEM7","price":10}},{"quantity":2000,"product":{"id":"item888","name":"ITEM8","price":15}},{"quantity":3000,"product":{"id":"item999","name":"ITEM9","price":20}}]**,"custom":{"id":"xyz123","name":"XZY"},"id":"57e941c0a8dbeb4c8c8f317c"}]}
The response of query (price greater than 15):
{"value":[{"orderItems":[{"quantity":300,"product":{"id":"item345","name":"ITEMC","price":20},"id":"57e30454d70bda6419c9922f"}],"custom":{"id":"efg123","name":"EFG"},"id":"a8dd0f23-46d9-4f6e-bffa-9709e7c23b87"},{"orderItems":[{"quantity":400,"product":{"id":"item456","name":"ITEMD","price":30},"id":"57e30474d70bda6419c99230"}],"custom":{"id":"hij123","name":"HIJ"},"id":"316efd3f-0b30-4ad1-ac22-2640a613142e"},**{"orderItems":[{"quantity":1000,"product":{"id":"item777","name":"ITEM7","price":10}},{"quantity":2000,"product":{"id":"item888","name":"ITEM8","price":15}},{"quantity":3000,"product":{"id":"item999","name":"ITEM9","price":20}}]**,"custom":{"id":"xyz123","name":"XZY"},"id":"57e941c0a8dbeb4c8c8f317c"}]}
Unfortunately, it's not support $expand / all / any
to query entities. But there has a way to make it work even it ugly.
You can add a ACTION for this resource, it's use mongoDB API to filter data. example:
server.resource('order', { product: [{ price: Number }] })
.action('/all-item-greater', (req, res, next) => {
const { price } = req.query;
const $elemMatch = { price: { $gt: price } };
server.resources.order.find()
.select({ product: { $elemMatch } })
.exec((err, data) => res.jsonp(data));
});
Thanks for the reply! but I met a small problem with const { price },
const { price } = req.query;
^
SyntaxError: Unexpected token {
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:373:25)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:974:3
ES6 syntax:
const { price } = req.query;
Same as ES5 syntax:
var price = req.query.price;
Hi ! The ES5 syntax seems working, whereas the query cannot get a result in my test..
GET orders(316efd3f-0b30-4ad1-ac22-2640a613142e)/all-item-greater?price=10
The response,
Cannot GET /orders(316efd3f-0b30-4ad1-ac22-2640a613142e)/all-item-greater?price=10
The data, I assume ACTION should also work in the case of non-multiple orderItems.
GET orders(316efd3f-0b30-4ad1-ac22-2640a613142e)/
{"orderItems":[{"quantity":400,"_id":"57e30474d70bda6419c99230","product":{"id":"item456","name":"ITEMD","price":30}}],"custom":{"id":"hij123","name":"HIJ"},"id":"316efd3f-0b30-4ad1-ac22-2640a613142e"}
Strange, it should be working. plz check your code is same as the example.