Using Linq, Trying to Use OrderBy on Object's Children - sql-server

Trying to use Linq with some Entity objects to do a crafty query here. Hoping for some help with a point I'm having a hard time finding decent documentation on:
Basically, I'm trying to use OrderBy to order against the child of an object I'm querying against. The difficult part is that the object has multiple children, and based on the object's type, I need to use one set of a children or another set of children to order by.
To clarify:
A can come in two types: i, or ii
If A is of type i, then I need to order by D: i.e, A has a B, which has many Cs, which has many Ds.
If A is of type ii, then I need to order by F: ie. A has an E, which has many Fs.
So the question is, how can I order by D and F, from A?
I'm hoping for something like:
IQueryable<AObject> aObj = query.OrderBy(aObject=> aObject.Type==i? aObject.B.C.D : aObject.E.F).Skip(offset).Take(limit).AsQueryable();
Of course, I'm also just confused as to how to order the D's, when C has a collection of Ds
Thoughts? And thanks in advance!

You need to use an aggregate function such as Min or Max to pick a value that represents the collection and use that value for the ordering. For example:
IQueryable<AObject> aObj = query.OrderBy(aObject =>
aObject.Type==i ?
aObject.B.Cs.Max(c => c.Ds.Max(d => d.Foo)) :
aObject.E.Fs.Max(f => f.Bar)
).Skip(offset).Take(limit).AsQueryable();

Related

How to do 'where model.field contains array' in Ecto?

Let's say I have a model with a field sizes that is an array (e.g. sizes: ['S', 'M', 'L']). What I want to accomplish, building an API, is for a user to be able to filter those models based on sizes. So a GET request to this path:
.../products?sizes=['S','M']
Should return all the products for which the given array is a subarray of their sizes field. So I don't want nor need an exact match but I want the users to be able to filter as explained above. How would I go about accomplishing this in my Phoenix API ?
I could only accomplish filtering the ones that contained a specific value (where: this in that), but if I pass in an array and I wanna check if that array is contained in that model field, I'm a bit lost.
Thanks in advance for any help, let me know if you need any additional information.
EDIT
I am trying to use fragment("? #> ?::varchar[]", p.sizes, ^params["sizes'] ) and it works, but it fails if I add any simple filter like [color: "red"] on top of the existing one, this means I can't create a set of filters and then add it to the where clauses like ... and ^filters
filters = Ecto.Changeset.cast(%Product{}, params, [], [:color])
|> Map.fetch!(:changes)
|> Map.to_list
# Do I need to actually do this check like this ? (It fails otherwise)
sizes = if is_nil(params["sizes"]) do [] else params["sizes"] end
products_query = from(
p in Product,
where: fragment("? #> ?::varchar[]", p.sizes, ^sizes) and
^filters
)
This doesn't currently work.
As you've figured out already, you need to use #> with fragment for the "array contains array" operation. For your second question, to chain where expressions with and, you can just add another where:
products_query = from(
p in Product,
where: fragment("? #> ?::varchar[]", p.sizes, ^sizes),
where: ^filters
)

Conditionally creating vertex in Titan

I have a situation where I need to check if a vertex with three satisfying properties property1='a',property2='b',property3='c' already exists in a graph and if it does not exist, I need to create it. Basically there should be a unique vertex in the graph with the combination of these three properties. I have tried out this snippet of gremlin code to check based on one property 'id'
getOrCreate = { id ->
def p = g.V('userId', id)
if (p.hasNext()) ? p.next() : g.addVertex([userId:id])
Not very clear about the best way to modify this to achieve what i need with gremlin since I'm a beginner. All I can think of is nesting more if's and else's in the last statement. Any help is appreciated, thank you.
There are several approaches. One way would be to extend your traversal a bit:
getOrCreate = { one, two, three ->
def p = g.V('prop1', one).has('prop2',two).has('prop3',three)
p.hasNext() ? p.next() : g.addVertex([prop1:one,prop2:two,prop3:three])
In the above code, prop1 represents an indexed property, then you just filter on the rest. That prop should be the most selective property in that it should filter out the most results.
If for some reason prop is not selective enough then this solution might not be fast enough. In other words, if you have 1 billion vertices and g.V('prop1', one) returns 100000 then you will be in-memory filtering those, which will be kinda slow. If this is your case, I would consider creating a "poor-man's" composite index, by adding a fourth property to index on that combines all three properties into one. Then just do your lookups on that.
You're almost there.
getOrCreate = { p1, p2, p3 ->
def p = g.V().has('property1', p1).has('property2', p2).has('property3', p3)
p.hasNext() ? p.next() : g.addVertex(['property1':p1,'property2':p2,'property3':p3])
}
Cheers,
Daniel

Predicate to zip two collections and use as binding source

I've got two collections, ObservableCollection<Lap> and a ObservableCollection<Racer> where Lap holds lap data of a car race and Racer, you guess it, the Racer's data. Both objects know the racerId.
Is there a way I can come up with a predicate to use that as a Zip-func to zip those two collections together? The reason I want to do that is to bind them DataGrid.
I had seen this, but can't quite see how to use it with a predicate.
I came up with that:
laps.Zip(participants, (lap, racer) => lap.EnrollmentId == racer.EnrollmentId);
But how would I map that to the DataGridColumns?
I think you are looking for a Join instead, since you do want to combine the properties of both based on a matching Id. For Zip() to work both collections must have the same number of entries in the same matching order already.
var results = from racer in participants
join l in laps
on racer.EnrollmentId equals l.EnrollmentId
select new
{
//select the properties you are interested in here
//or just use both:
Racer = racer,
Lap = l
}

Mongoid Syntax Questions

1) Finding by instance object
Assuming I have the instance object called #topic. I want to retrieve the answers for this given topic. I was thinking I should be able to pass in :topics=>#topic, but i had to do the very ugly query below.
#answers = Answers.where(:topic_ids => {"$in" => [#topic.id]})
2) Getting the string representation of the id. I have a custom function (shown below). But shouldn't this be a very common requirement?
def sid
return id.to_s
end
If your associations are set up correctly, you should be able to do:
#topic.answers
It sounds like the above is what you are looking for. Make sure you have set up your associations correctly. Mongoid is very forgiving when defining associations, so it can seem that they are set up right when there is in fact a problem like mismatched names in references_many and referenced_in.
If there's a good reason why the above doesn't work and you have to use a query, you can use this simple query:
#answers = Answer.where(:topic_ids => #topic.id)
This will match any Answer record whose topic_ids include the supplied ID. The syntax is the same for array fields as for single-value fields like Answer.where(:title => 'Foo'). MongoDB will interpret the query differently depending on whether the field is an array (check if supplied value is in the array) or a single value (check if the supplied value is a match).
Here's a little more info on how MongoDB handles array queries:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray

What is an appropriate data structure and database schema to store logic rules?

Preface: I don't have experience with rules engines, building rules, modeling rules, implementing data structures for rules, or whatnot. Therefore, I don't know what I'm doing or if what I attempted below is way off base.
I'm trying to figure out how to store and process the following hypothetical scenario. To simplify my problem, say that I have a type of game where a user purchases an object, where there could be 1000's of possible objects, and the objects must be purchased in a specified sequence and only in certain groups. For example, say I'm the user and I want to purchase object F. Before I can purchase object F, I must have previously purchased object A OR (B AND C). I cannot buy F and A at the same time, nor F and B,C. They must be in the sequence the rule specifies. A first, then F later. Or, B,C first, then F later. I'm not concerned right now with the span of time between purchases, or any other characteristics of the user, just that they are the correct sequence for now.
What is the best way to store this information for potentially thousands of objects that allows me to read in the rules for the object being purchased, and then check it against the user's previous purchase history?
I've attempted this, but I'm stuck at trying to implement the groupings such as A OR (B AND C). I would like to store the rules in a database where I have these tables:
Objects
(ID(int),Description(char))
ObjectPurchRules
(ObjectID(int),ReqirementObjectID(int),OperatorRule(char),Sequence(int))
But obviously as you process through the results, without the grouping, you get the wrong answer. I would like to avoid excessive string parsing if possible :). One object could have an unknown number of previous required purchases. SQL or psuedocode snippets for processing the rules would be appreciated. :)
It seems like your problem breaks down to testing whether a particular condition has been satisfied.
You will have compound conditions.
So given a table of items:
ID_Item Description
----------------------
1 A
2 B
3 C
4 F
and given a table of possible actions:
ID_Action VerbID ItemID ConditionID
----------------------------------------
1 BUY 4 1
We construct a table of conditions:
ID_Condition VerbA ObjectA_ID Boolean VerbB ObjectB_ID
---------------------------------------------------------------------
1 OWNS 1 OR MEETS_CONDITION 2
2 OWNS 2 AND OWNS 3
So OWNS means the id is a key to the Items table, and MEETS_CONDITION means that the id is a key to the Conditions table.
This isn't meant to restrict you. You can add other tables with quests or whatever, and add extra verbs to tell you where to look. Or, just put quests into your Items table when you complete them, and then interpret a completed quest as owning a particular badge. Then you can handle both items and quests with the same code.
This is a very complex problem that I'm not qualified to answer, but I've seen lots of references to. The fundamental problem is that for games, quests and items and "stats" for various objects can have non-relational dependencies. This thread may help you a lot.
You might want to pick up a couple books on the topic, and look into using LUA as a rules processor.
Personally I would do this in code, not in SQL. Each item should be its own class implementing an interface (i.e. IItem). IItem would have a method called OkToPurchase that would determine if it is OK to purchase that item. To do that, it would use one or more of a collection of rules (i.e. HasPreviouslyPurchased(x), CurrentlyOwns(x), etc.) that you can build.
The nice thing is that it is easy to extend this approach with new rules without breaking all the existing logic.
Here's some pseudocode:
bool OkToPurchase()
{
if( HasPreviouslyPurchased('x') && !CurrentlyOwns('y') )
return true;
else
return false;
}
bool HasPreviouslyPurchased( item )
{
return purchases.contains( item )
}
bool CurrentlyOwns( item )
{
return user.Items.contains( item )
}

Resources