Reputation: 32
I am trying to write a Breeze query for the Northwind database to show orders that contain all three products that a user specifies. So if a user selects ProductID 41, 51, and 65 from drop downs, the query would return order id 10250.
This is just a sample scenario that I am looking to base another query on in a project I am working on, but I thought using Northwind to explain it would be easier than describing the project. I can easily do it in T-SQL using derived tables, but I need to get the parameters from the client. Any thoughts? Thanks in advance!
Upvotes: 0
Views: 680
Reputation: 514
If you're still interested in doing this on the client, you can try the following Breeze query.
var listOfProductIds = [41, 51, 65];
var preds = listOfProductIds.map(function (id) {
return Predicate.create("OrderDetails", "any", "ProductID", "==", id);
});
var whereClause = Predicate.and(preds);
var query = EntityQuery.from('Orders').where(whereClause);
This will retrieve all Orders that have at least all 3 of the Products specified.
To further filter this so you have all Orders that have only all 3 of the Products specified, you can write,
entityManager.executeQuery(query)
.then(filterOrders);
//once you get results on the client
function filterOrders(data) {
var allOrders = data.results;
var filteredOrders = allOrders.filter(function (o) {
return o.OrderDetails.length == listOfProductIds.length;
});
}
You can only filter on the client since OData doesn't yet support the Aggregate Count function like Linq to Entities does. This is probably not ideal but it's an option if you decide not to do it on the server.
Upvotes: 1
Reputation: 17052
You can use the EntityQuery.withParameters method to call a server side query that has your linq query. i.e. something like this.
// On the client
var query = EntityQuery.from("GetOrdersWithProductIds")
.withParameters({ productIds: [41, 51, 65] });
// On the server
[HttpGet]
public IQueryable<Order> GetOrdersWithProductIds([FromUri] int[] productIds) {
return ContextProvider.Context.Orders.Where(... your linq query here ...);
}
or you might try using the support for 'any'/'all' query operators. i.e. something like this.
var predicate = breeze.Predicate("ProductID", "==", 41)
.or("ProductID", "==", 51)
.or("ProductID", "==", 65);
var query = EntityQuery.from("Orders")
.where("OrderDetails", "all", predicate)
Upvotes: 0
Reputation: 14995
Sorry in my comment I said look at the and()
method but in actuality for your use you needed to look at the or()
method -
var p1 = breeze.Predicate("Product.ProductID", "==", 41);
var p2 = breeze.Predicate("Product.ProductID", "==", 51);
var p3 = breeze.Predicate("Product.ProductID", "==", 65);
var newPred = breeze.Predicate.or(p1, p2, p3);
var query = EntityQuery.from('Order_Details').select('Order.OrderID').where(newPred);
The only issue with these queries on the client is that depending on how you are building them client-side and how many predicates you are adding they can get very long in some situations, such as select all 200 records except 1 id
type queries which can bite you on IE8.
Upvotes: 0