Query in an array - hyperledger-composer

I have a model designed like that
asset Myasset identified by assetId {
o String assetId
o String[] elements
}
I would to make a query, but I don't found how to request an element in the array.
I badly tryed the simple way
query Q1 {
description: "Example query in an array"
statement:
SELECT zzz.yyy.xxx.Myasset
WHERE
(elements[0] == "Request")
}
But it doesn't work
Is there a statement equivalent of the SQL IN ? To have something like
"Request" IN elements

we do not yet support queries across elements in an array. If you wish to create a Github issue for this, that would be good.

Currently IN is not supported by Hyperledger Query Language,
You can do like this: (elements CONTAINS "Request")
Already answered here: #1701

Related

Composer query to match a participant reference

So I have a query like this:
query selectOrder{
description: "Select an Order that matches a Client reference and an Order Number"
statement:
SELECT com.x.Order
WHERE (client == _$client AND orderNumber == _$orderNumber)
}
The order is something like this:
asset Order identified by uuid {
o String uuid
--> Client client
o String orderNumber
--> Item[] items
}
How do I pass the reference to the client to the query?
I tried the reference and was told to toJSON it.
I tried that and it won't parse the thing - there's a clear issue with the parsing of the query.
I can't find the answer in the docs, so I'm wondering if anyone has done this or if I have to save the client id instead of the reference to client and lose the integrity.
EDIT: For completeness for the first answer below.
I'm trying to add an Item to the array of Items.
My Item object is defined like this:
asset Item identified by uuid {
o String uuid
o DateTime timestamp
o String orderNumber
--> Client client
o String[] message
}
When the transaction is invoked the single object passed in is the Item.
I'm setting Item.client as the _$client value in the query.
Should I be pre-pending it with "resource:"?
I'm asking because I thought that was in the reference string already - at least it is in the view in the playground.
EDIT2:
So I manually construct the following variable:
var RSRC = 'resource:com.x.Client#XYZ123'
Set that as the client in this query
return query('selectOrder', {agency : RSRC, orderNumber : orderNumber});
But I'm still getting this:
Error: unknown operator "0" - should be one of $eq, $lte, $lt, $gt,
$gte, $exists, $ne, $in, $nin, $size, $mod, $regex, $elemMatch, $type
or $all
What next?
Embedding the "resource..." string in quotes didn't work either.
Your query looks ok, but you need to pass a string with the format:
resource:type.Name#instance for the relationship.
E.g. resource:org.acme.Car#123ABC

Get all the includes from an Entity Framework Query?

I've the following Entity Model : Employee has a Company and a Company has Employees.
When using the Include statement like below:
var query = context.Employees.Include(e => e.Company);
query.Dump();
All related data is retrieved from the database correctly. (Using LEFT OUTER JOIN on Company table)
The problem is hat when I use the GroupBy() from System.Linq.Dynamic to group by Company.Name, the Employees are missing the Company data because the Include is lost.
Example:
var groupByQuery = query.GroupBy("new (Company.Name as CompanyName)", "it");
groupByQuery.Dump();
Is there a way to easily retrieve the applied Includes on the 'query' as a string collection, so that I can include them in the dynamic GroupBy like this:
var groupByQuery2 = query.GroupBy("new (Company, Company.Name as CompanyName)", "it");
groupByQuery2.Dump();
I thought about using the ToString() functionality to get the SQL Command like this:
string sql = query.ToString();
And then use RegEx to extract all LEFT OUTER JOINS, but probably there is a better solution ?
if you're creating the query in the first place - I'd always opt to save the includes (and add to them if you're making a composite query/filtering).
e.g. instead of returning just 'query' return new QueryContext {Query = query, Includes = ...}
I'd like to see a more elegant solution - but I think that's your best bet.
Otherwise you're looking at expression trees, visitors and all those nice things.
SQL parsing isn't that straight either - as queries are not always that simple (often a combo of things etc.).
e.g. there is a `span' inside the query object (if you traverse a bit) which seems to be holding the 'Includes' but it's not much help.

LINQ Query to find all tags?

I have an application that manages documents called Notes. Like a blog, Notes can be searched for matches against one or more Tags, which are contained in a Note.Tags collection property. A Tag has Name and ID properties, and matches are made against the ID. A user can specify multiple tags to match against, in which case a Note must contain all Tags specified to match.
I have a very complex LINQ query to perform a Note search, with extension methods and looping. Quite frankly, it has a real code smell to it. I want to rewrite the query with something much simpler. I know that if I made the Tag a simple string, I could use something like this:
var matchingNotes = from n in myNotes
where n.Tags.All(tag => searchTags.Contains(tag))
Can I do something that simple if my model uses a Tag object with an ID? What would the query look like. Could it be written in fluent syntax? what would that look like?
I believe you can find notes that have the relevant tags in a single LINQ expression:
IQueryable<Note> query = ... // top part of query
query = query.Where(note => searchTags.All(st =>
note.Tags.Any(notetag => notetag.Id == st.Id)));
Unfortunately there is no “fluent syntax” equivalent for All and Any, so the best you can do there is
query = from note in query
where searchTags.All(st =>
note.Tags.Any(notetag => notetag.Id == st.Id))
select note;
which is not that much better either.
For starters see my comment; I suspect the query is wrong anyway! I would simplifiy it, by simply enforcing separately that each tag exists:
IQueryable<Note> query = ... // top part of query
foreach(var tagId in searchTagIds) {
var tmpId = tagId; // modified closures...
query = query.Where(note => note.Tags.Any(t => t.Id == tmpId));
}
This should have the net effect of enforcing all the tags specified are present and accounted for.
Timwi's solution works in most dialects of LINQ, but not in Linq to Entities. I did find a single-statement LINQ query that works, courtesy of ReSharper. Basically, I wrote a foreach block to do the search, and ReSharper offered to convert the block to a LINQ statement--I had no idea it could do this.
I let ReSharper perform the conversion, and here is what it gave me:
return searchTags.Aggregate<Tag, IQueryable<Note>>(DataStore.ObjectContext.Notes, (current, tag) => current.Where(n => n.Tags.Any(t => t.Id == tag.Id)).OrderBy(n => n.Title));
I read my Notes collection from a database, using Entity Framework 4. DataStore is the custom class I use to manage my EF4 connection; it holds the EF4 ObjectContext as a property.

Linq Containsfunction problem

I use Ria Service domainservice for data query.
In My database, there is a table People with firstname, lastname. Then I use EF/RIA services for data processing.
Then I create a Filter ViewModel to capture user inputs, based it the input, I construct a linq Query to access data.
At server side, the default DomainService query for person is:
public IQueryable<Person> GetPerson()
{
return this.Context.Person;
}
At client side, the linq Query for filter is something like(I use Contains function here):
if (!String.IsNullOrEmpty(this.LastName))
q = q.Where(p => (p.LastName.Contains(this.LastName)));
The generated linq query is something like(when debugging,I got it):
MyData.Person[].Where(p => (p.LastName.Contains(value(MyViewModel.PersonFilterVM).LastName) || p.Person.LegalLastName.Contains(value(MyViewModel.PersonFilterVM).LastName)))
When I run the app, I put "Smith" for last name for search, but the result is totally irrelevant with "Smith"!
How to fix it?
I'm guessing here as to what your error is so this might not work for you.
In your 2nd code snippet you do the following.
q = q.Where(p => (p.LastName.Contains(this.LastName)));
This is where I think your error is. Linq does not evaluate the where clause until you iterate over it. Try changing the line to the following.
qWithData = q.Where(p => (p.LastName.Contains(this.LastName))).ToList();
The .ToList() call will load the query with data.
When you check in the debugger, does value(MyViewModel.PersonFilterVM).LastName evaluate to Smith at the time the query is resolved?
Recall that queries are not resolved until they are enumerated.

Entity Framework - "Unable to create a constant value of type 'Closure type'..." error

Why do I get the error:
Unable to create a constant value of type 'Closure type'. Only
primitive types (for instance Int32, String and Guid) are supported in
this context.
When I try to enumerate the following Linq query?
IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
var myList = from person in entities.vSearchPeople
where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}
Update:
If I try the following just to try to isolate the problem, I get the same error:
where upperSearchList.All(arg => arg == arg)
So it looks like the problem is with the All method, right? Any suggestions?
It looks like you're trying to do the equivalent of a "WHERE...IN" condition. Check out How to write 'WHERE IN' style queries using LINQ to Entities for an example of how to do that type of query with LINQ to Entities.
Also, I think the error message is particularly unhelpful in this case because .Contains is not followed by parentheses, which causes the compiler to recognize the whole predicate as a lambda expression.
I've spent the last 6 months battling this limitation with EF 3.5 and while I'm not the smartest person in the world, I'm pretty sure I have something useful to offer on this topic.
The SQL generated by growing a 50 mile high tree of "OR style" expressions will result in a poor query execution plan. I'm dealing with a few million rows and the impact is substantial.
There is a little hack I found to do a SQL 'in' that helps if you are just looking for a bunch of entities by id:
private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}
where pkIDColumn is your primary key id column name of your Entity1 table.
BUT KEEP READING!
This is fine, but it requires that I already have the ids of what I need to find. Sometimes I just want my expressions to reach into other relations and what I do have is criteria for those connected relations.
If I had more time I would try to represent this visually, but I don't so just study this sentence a moment: Consider a schema with a Person, GovernmentId, and GovernmentIdType tables. Andrew Tappert (Person) has two id cards (GovernmentId), one from Oregon (GovernmentIdType) and one from Washington (GovernmentIdType).
Now generate an edmx from it.
Now imagine you want to find all the people having a certain ID value, say 1234567.
This can be accomplished with a single database hit with this:
dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));
IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);
Do you see the subquery here? The generated sql will use 'joins' instead of sub-queries, but the effect is the same. These days SQL server optimizes subqueries into joins under the covers anyway, but anyway...
The key to this working is the .Any inside the expression.
I have found the cause of the error (I am using Framework 4.5). The problem is, that EF a complex type, that is passed in the "Contains"-parameter, can not translate into an SQL query. EF can use in a SQL query only simple types such as int, string...
this.GetAll().Where(p => !assignedFunctions.Contains(p))
GetAll provides a list of objects with a complex type (for example: "Function"). So therefore, I would try here to receive an instance of this complex type in my SQL query, which naturally can not work!
If I can extract from my list, parameters which are suited to my search, I can use:
var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))
Now EF no longer has the complex type "Function" to work, but eg with a simple type (long). And that works fine!
I got this error message when my array object used in the .All function is null
After I initialized the array object, (upperSearchList in your case), the error is gone
The error message was misleading in this case
where upperSearchList.All(arg => person.someproperty.StartsWith(arg)))

Resources