I am looking if there is a way (maybe using a library or if neo4j supports this), to generate a Cypher query from a Visual Model of a query.
This is what I mean, I may have a visual query (which I am creating myself say using zoomcharts) in my app which looks like this:
screnshot
This query looks for all persons who live in city Vienna.
Of course I can get list of nodes and their relationships say as JSON data out of this visual model.
What I want is from this to generate a Cypher query (out of this visual model and say the JSON data I generate from the visual model).
Do you know if there is a tool or library (or maybe it is supported by neo4j in some way) to help me achieve this?
IMHO my question is similar to this one, however that one is 4 years old and doesn't contain much helpful info.
If you use arrows to create your visual model, you can export it to Cypher :
http://www.apcjones.com/arrows/#
Such a query can be represented as a sequence of matches for nodes and relationships:
MATCH (N0:`Person`)
MATCH (N1:`City` {`name`:"Vienna"})
MATCH (N0)-[R0:`lives in`]->(N1)
RETURN *
And this can easily be built from JSON:
const nodesMatch = []
graph.nodes.forEach(function(n) {
const nodeVar = 'N' + n.id
const nodeLabels = '`' + n.labels.join(':') + '`'
nodesMatch.push(
'MATCH (' + nodeVar + ':' + nodeLabels + ')'
)
})
[ https://jsfiddle.net/mx9hmdq4/ ]
P.S. I also recommend that you pay attention to popoto:
Visual query builder for Neo4j graph database - https://github.com/Nhogs/popoto
Related
As the error says, I think LLBLGen have their own custom functions but official documentation doesn't help much. Is there any way to concatenate these two strings and make into one while LINQ querying?
var viewModelCarrierDivisionQuery = from division in database.CarrierDivision
where division.CarrierId == carrierId
join carrier in database.Carrier
on division.CarrierId equals carrier.CarrierId
select new CarrierDetailViewModel.DivisionModel {
Id = division.CarrierDivisionId,
Name = string.Join(" / ", carrier.Name, division.DivisionName)
};
SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException: 'Method call to 'Join' doesn't have a known mapped database function or other known handler.'
What I have used is just a simple solution with plus name +" / "+name. This works. Is there any better way out there?
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.
I'm trying to write a LINQ expression that will join two tables and return data in a format similar to what is possible using MySql's GROUP_CONCAT. I tried searching around on Google and SO, but all the results I found used MSSQL or were only using one table. The expression I have written now looks like this:
from d in division
join o in office on d.Id = o.DivisionId
select new
{
id = d.Id,
cell = new string[] { d.DivisionName, o.OfficeName }
}
As expected, this returns a list of every division and what offices correspond to that division. The only problem is that since most divisions will have more than one office, I get a division back for each office in said division. Essentially I'm seeing results like this:
Division1: Office1
Division1: Office2
Division1: Office3
Division2: Office1
When I want to see:
Division1: Office1, Office2, Office3
Division2: Office1
I remember doing something a while ago with MySql that used GROUP_CONCAT, but I can't figure out what the equivalent of that would be using LINQ. I tried writing a method which had an IEnumerable<Office> parameter and built a string using the Aggregate extension method, but the way I have my LINQ expression written now, each Office is passed in rather than an IEnumerable<Office>. Is there a better way to approach this problem than what I'm doing now? I'm rather new to LINQ expressions, so I apologize if this is trivial.
You want a group join, e.g.
from d in division
join o in office on d.Id = o.DivisionId into offices
select new
{
id = d.Id,
divisionName = d.DivisionName,
officeNames = offices.Select(o => o.OfficeName)
}
Is there a way to use a LINQ expression to request a Count query from the Netflix oData service in Silverlight 4?
The Netflix documentation shows that you can return counts by appending $count to a request for a collection, but a URL like this:
http://netflix.cloudapp.net/Catalog/Genres/$count
Is not generated from an expression like this:
var count = (from g in catalog.Genres select g).Count();
The above code returns an error saying that the Count method is not supported. Is there a way to do this in LINQ, or do I just need to make WebClient request to get the value?
Count and LongCount are not supported in Silverligth because they require a synchornous execution of the query. Since Silverlight requires all network operations to by asynchronous this is not possible.
You can either issue the HTTP query in question programatically not using DataServiceContext (or related classes), since the $count returns a text representation of the number, parsing the response is not that hard.
Or you can use a bit of a trick. You can use IncludeTotalCount() to add $inlinecount=allpages query option to the query which will include the count in the response. Then to not download all the entities from server, you can use Take(0) which will add $top=0 and thus return empty result set. But the inline count will still contain the right number.
You can access the inline count on the QueryOperationResponse.TotalCount property.
Something like this:
NetflixCatalog ctx = new NetflixCatalog(new Uri("http://netflix.cloudapp.net/Catalog"));
var q = (DataServiceQuery<Genre>)ctx.Genres.IncludeTotalCount().Take(0);
q.BeginExecute((ar) =>
{
QueryOperationResponse<Genre> r = (QueryOperationResponse<Genre>)q.EndExecute(ar);
r.TotalCount.ToString(); // Use the count in whatever way you need
}, null);
It works in LinqPad 4 using C# 4.0
var count = (from g in Genres select g).Count();
count.Dump();
Result: 518
In LinqPad 2 using C# 3.0 the error appears.
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)))