Neo4jClient : C# query to fetch collection with multiple columns - neo4j

How one can fetch multiple columns data using neo4jClient -
For eq. the example shown on link
Cyper query to fetch multiple column collection
The sample shown above passes properties of event node for collection instead of complete event node.
The query I am constructing takes few properties from the event node and few properties from the relation.
For eq. The relation attribute "registerd_on" needs to be added.
So how to pass multiple properties for collection ?

It's not very nice, but if you look at what is returned by doing a collection you get an array of arrays, but these arrays don't have properties as such, so you can only really parse them as string.
Using the :play movies dataset as a base:
var query = gc.Cypher
.Match("(p:Person {name:'Tom Hanks'})-->(m:Movie)")
.With("p, collect([m.title, m.released]) as collection")
.Return((p, collection) => new
{
Person = p.As<Person>(),
Collection = Return.As<IEnumerable<IEnumerable<string>>>("collection")
});
where Person is :
public class Person
{
public string name { get; set; }
}
You can then access the data like so:
foreach (var result in results)
{
Console.WriteLine($"Person: {result.Person.name}");
foreach (var collection in result.Collection)
{
foreach (var item in collection)
{
Console.WriteLine($"\t{item}");
}
}
}
which is not nice :/

Related

Batching Neo4J updates for speed

My goal is to have a list of words in the Oxford dictionary with a relationship between them called IS_ONE_STEP_AWAY_FROM. Each word in relationship is the same length and varies by only one letter.
I am currently able to batch insert the words themselves, but how can I batch insert these relationships?
class Word
{
public string Value { get; set; }
}
public void SeedDatabase()
{
var words = new Queue<Word>();
EnqueueWords(words);
//Create the words as a batch
GraphClient.Cypher
.Create("(w:Word {words})")
.WithParam("words", words)
.ExecuteWithoutResults();
//Add relationships one word at a time
while (words.Count > 0)
{
var word = words.Dequeue();
var relatedWords = WordGroups[word.Value].Except(Enumerable.Repeat(word.Value, 1)).ToList();
if (relatedWords.Count > 0)
{
foreach (string relatedWord in relatedWords)
{
GraphClient.Cypher
.Match("(w1 :Word { Value : {rootWord} }), (w2 :Word { Value : {relatedWord} })")
.Create("(w1)-[r:IS_ONE_STEP_AWAY_FROM]->(w2)")
.WithParam("rootWord", word.Value)
.WithParam("relatedWord", relatedWord)
.ExecuteWithoutResults();
}
}
}
}
Peter do you have an index or constraint on :Word(Value) ?
I also don't fully understand how this batches:
GraphClient.Cypher
.Create("(w:Word {words})")
.WithParam("words", words)
.ExecuteWithoutResults();
And where you define the property-name (aka Value).
Do you run this currently concurrently?
For the relationships I'd recommend to group them by start-word.
then you could do something like:
MATCH (w1:Word {Value:{rootWord}})
UNWIND {relatedWords} as relatedWord
MATCH (w2:Word {Value:relatedWord}}
CREATE (w1)-[r:IS_ONE_STEP_AWAY_FROM]->(w2);
Neo4jClient also still have to learn to use the new transactional endpoint.

Filtering list using linq and mvc

Below is the code in question. I receive Object reference not set to an instance of an object. on the where clause inside the Linq query. However, this only happens after it goes through and builds my viewpage.
Meaning: If I step through using debugger, I can watch it pull the correct order I am filtering for, go to the correct ViewPage, fill in the model/table with the correct filtered item, and THEN it comes back to my Controller and shows me the error.
public ActionResult OrderIndex(string searchBy, string search)
{
var orders = repositoryOrder.GetOpenOrderList();
if (Request.QueryString["FilterOrderNumber"] != null)
{
var ordersFiltered = from n in orders
where n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n;
return View(ordersFiltered);
}
return View(orders);
}
its always better to manipulate your strings and other things outside the linq query ,
please refer : http://msdn.microsoft.com/en-us/library/bb738550.aspx
from the readability point of view also its not good ,
public ActionResult OrderIndex(string searchBy, string search)
{
var orders = repositoryOrder.GetOpenOrderList();
var orderNumber = Request.QueryString["FilterOrderNumber"];
if (!string.IsNullOrEmpty(orderNumber))
{
orderNumber = orderNumber.ToUpper();
var ordersFiltered = from n in orders
where n.OrderNumber.ToUpper().Contains(orderNumber)
select n;
return View(ordersFiltered);
}
return View(orders);
}
Your query is not being executed in your Action method because you don't have a ToList (or equivalent) added to your query. When your code returns, your query will be enumerated somewhere in your view and that's the point where the error occurs.
Try adding ToList to your query like this to force query execution in your action method:
var ordersFiltered = (from n in orders
where n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n).ToList();
What's going wrong is that a part of your where clause is null. This could be your query string parameter. Try moving the Request.QueryString part out of your query and into a temporary variable. If that's not the case make sure that your orders have an OrderNumber.
You both were right. Just separately.
This fixed my problem
var ordersFiltered = (from n in orders
where !string.IsNullOrEmpty(n.OrderNumber) && n.OrderNumber.ToUpper().Contains(Request.QueryString["FilterOrderNumber"].ToUpper().ToString())
select n);

Mvc: Linq OrderBy custom parameter

I have the next linq query
public IEnumerable<Table> GetTablePage(int pageNumber, int pageSize, string searchCriteria)
{
Entities db = new Entities();
if (pageNumber < 1)
{
pageNumber = 1;
}
return entities.Table.OrderBy(searchCriteria).Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
}
It´s working fine, but i have some table fields where i need to do some joins for retrieving information, it's because in my Table i only have the code and i really need the name.
Example -> customerId is foreign key in Table, and i would like to get the customerName, but actually i can´t because entities.Table only has customerId, What´s the best way to return the information without losing Table.OrderBy(searchCriteria)... properties ? Thanks in advance.
I suppose that you are using Dynamic Linq to pass a string to your orderBy.
How do you filter your result with an OrderBy? i suppose that you try to filter using your searchCriteria?
Now some kind of answer might be....
If you include the child table in your query, then the child will be a part of your Table object.
entities.Table.Include("Customer").OrderBy(....

iterate through array and compare to entity object

I'm trying to get the various items in a one to many relationship of database objects. So I have the entity framework create my locations object and one column in the table has a comma separated list of services available at a location. I use:
var data = pubDB.Locations.Include("Branch_Ameneties");
in the model to get the relationsihp between a the two tables. Then in the view I am trying to iterate through the features in an array and get the associated Branch Amenities:
#foreach (var Location in Model.LocationListings())
{
#if (Location.Features != null)
{
string[] featureset = Location.Features.Split(',');
foreach (var item in featureset)
{
var feature = Location.Branch_Ameneties.Amenity.Where(x => Location.Branch_Ameneties.FID = Convert.ToInt32(item);
#feature
}
}
And I can't seem to get the array to associate with the reference table of amentiites.
instead of using the where clause, try using:
var feature = Location.Branch_Ameneties.Amenity.Single(x => Location.Branch_Ameneties.FID == Convert.ToInt32(item));
Also, you had "..FID = Convert.ToInt32(item)" instead of "..FID == Convert..."

LINQ to Entities query with join inside method for use in MVC app

In my Person table is a RequestedLocation column which stores location IDs. The IDs match the LocationId column in the Locations table, the Locations table also has the text location names, in the LocatioName column.
In my view, I need to display the string LocationName in the view which has the Person model passed to it. The view will be displaying a List of people in a telerik grid. CUrrently it works great, except the RequestedLocation column is all integers.
I am populating all my grids with methods containing LINQ queries. Here is the method that currently works:
public List<Person> GetPeople()
{
var query = from p in _DB.Person.ToList()
select p;
return query.ToList();
}
Here is the regular SQL query that works, and I need to convert into LINQ:
SELECT ApplicantID
,FirstName
,LastName
,MiddleName
,DateofBirth
,Gender
,RequestedVolunteerRole
,RequestedVolunteerLocation
,l.LocationName
FROM Form.Person p
JOIN dbo.Location l ON p.RequestedVolunteerLocation = l.LocationID
Order BY ApplicantID
Here is my attempt to convert to LINQ:
public List<NewApplicantViewModel> GetPeople()
{
var query = from pl in _DB.Person.ToList()
join l in _Elig_DB.Locations.ToList() on pl.RequestedVolunteerLocation equals l.LocationID
select new
{
pl.RequestedVolunteerLocation = l.LocationName
};
return query.ToList();
The number of errors I get from this are numerous, but most are along the lines of:
Cannot convert from type Annonymous to Type List<NewAPplicantModel>
and
Invalid annonymous type declarator.
Please help, and thank you for reading my post.
Oh, and I have only been programming for a couple months, so if I am going about this all wrong, please let me know. Only thing I have to stick with is the table structure because it is an existing app that I am updating, and changing the location or person tables would have large consequences.
public List<NewApplicantViewModel> GetPeople()
{
var query = from pl in _DB.Person
join l in _Elig_DB.Locations on pl.RequestedVolunteerLocation
equals l.LocationID
select new NewApplicantViewModel
{
LocationName = l.LocationName,
otherPropery = p.Property
};
return query.ToList();
}
Beware of calling _DB.Person.ToList() it will load all persons from DB because ToList() immediately executes the query and the join would be performed in memory (not in DB).
The reason you are getting an error is you are projecting an anonymous type
select new
{
pl.RequestedVolunteerLocation = l.LocationName
};
Instead, you need to project a NewApplicantViewModel
select new NewApplicantViewModel
{
RequestedVolunteerLocation = l.LocationName
};

Resources