Neo4jClient Create Unique results in multiple duplicate nodes - neo4j

I was wondering if some one can help me understand how Create Unique actually works in Neo4J. I am trying to register multiple addresses to a shipper node, where I expect the City, State and country to be same across the addresses so that they all point to the same node. However the issue is that the Create Unique is resulting in multiple instance of same node in the database.
Here is the function I have to register an address with the shipper which I call multiple times with same Shipper node, but different address pointing to same city.
public Node<Address> RegisterShipperAddress(Node<Shipper> shipper,AddressType addressType ,Address address, City city, State state, Country country)
{
var shipperRef = shipper.Reference;
var addressRef = neo4jClient.Cypher.Start(new { shipperNode = shipperRef }).CreateUnique("(shipperNode)-[r:HAS_ADDRESS { TypeName:{TypeName} }]->(addressRef{address})").WithParam("TypeName", addressType.TypeName).WithParam("address", address).Return<Node<Address>>("addressRef").Results.FirstOrDefault();
var cityRef = neo4jClient.Cypher.Start(new { addressNode = addressRef }).CreateUnique("(addressNode)-[:BELONGS_TO_CITY]->(cityRef{cityData})").WithParam("cityData", city).Return<Node<City>>("cityRef").Results.FirstOrDefault();
var stateRef = neo4jClient.Cypher.Start(new { cityNode = cityRef }).CreateUnique("(cityNode)-[:BELONGS_TO_STATE]->(stateRef{stateData})").WithParam("stateData", state).Return<Node<State>>("stateRef").Results.FirstOrDefault();
var countryRef = neo4jClient.Cypher.Start(new { stateNode = stateRef }).CreateUnique("(stateNode)-[:BELONGS_TO_COUNTRY]->(countryRef{stateData})").WithParam("stateData", state).Return<Node<Country>>("countryRef").Results.FirstOrDefault();
return addressRef;
}
Now suppose I call the the above method with different address as below:
//First Call....
RegisterShipperAddress(shipperNode,
new AddressType { TypeName = "REGISTRED" },
new Address
{
Address1 = "151/1 ABC Main",
Address2 = "My PO 1234",
Email = "abc#abc.com",
Mobile = "123456",
Phone = "123456"
},
new City { InternalId = 1, Label = "MyCity" },
new State { InternalId = 1, Label = "MyState" },
new Country { InternalId = 1, Label = "MyCountry" }
);
// Second call
RegisterShipperAddress(shipperNode,
new AddressType { TypeName = "BILLING" },
new Address
{
Address1 = "1 X Main Road",
Address2 = "PO 555",
Email = "abc#abc.com",
Mobile = "123456",
Phone = "123456"
},
new City { InternalId = 1, Label = "MyCity" },
new State { InternalId = 1, Label = "MyState" },
new Country { InternalId = 1, Label = "MyCountry" }
);
I end up with multiple instances of same node. Just wondering if its even possible to achieve this using the Create Unique clause of Cypher.
Here is the kind if graph I see..
--> (Address1)-->(MyCity)-->(MyState)-->(MyCountry)
(root) -->(Shipper) ||
--> (Address2)-->(MyCity)-->(MyState)-->(MyCountry)
Also whats the best way to create multiple nodes at once in one transaction, I think in the above code, each nodes are created in a separate Transactions.

CREATE UNIQUE in Cypher 1.9 is not encouraged.Please, if you can, use Neo4j 2.0.0.M05 ++ and create a unique constraint on Cities, States and Countries, see http://docs.neo4j.org/chunked/snapshot/query-constraints.html#constraints-create-uniqueness-constraint and then MERGE the city node, the create the address. Here a graphgist example:
http://gist.neo4j.org/?6549962

Related

Spliton in Dapper, ASP NET Core

string query = #"SELECT
l.LoginId,
l.Email,
un.UserNameId,
un.Name,
un.CPF,
un.CellPhone,
ga.GroupId,
ga.Name
FROM Tb_Login l
INNER JOIN Tb_UserName un
ON un.IdLogin = l.LoginId
INNER JOIN Tb_GroupAccess ga
ON ga.GroupId = l.IdGroupAccess
WHERE un.IdLogin = #Id
AND l.IdStatusLogin = 1";
var obj = _connection.Query<EmployeeResponse, Login, UserName, GroupAccess, EmployeeResponse>(
sql: query,
map: (loginResponse, login, userName, groupAcess) =>
{
loginResponse.Login = login;
loginResponse.UserName = userName;
loginResponse.GroupAccess = groupAcess;
return loginResponse;
},
splitOn: "UserNameId,GroupId",
param: new
{
Id = request.IdEmployee
}
).FirstOrDefault();
This code is returning:
System.ArgumentException: 'Multi-map error: splitOn column 'UserNameId' was not found - please ensure your splitOn parameter is set and in the correct order Arg_ParamName_Name'
I'm having problems trying to do this spliton.
As I stated in my comment: The first EmployeeResponse in the query shouldn't be there. It should say _connection.Query<Login, UserName, GroupAccess, EmployeeResponse> meaning: Map to Login, UserName and GroupAccess, return an EmployeeResponse. There is nothing in the query that can be mapped directly to EmployeeResponse
Therefore you also need to create the employee response yourself, so the code becomes something like:
var obj = _connection.Query<Login, UserName, GroupAccess, EmployeeResponse>(
sql: query,
map: (login, userName, groupAccess) =>
{
return new EmployeeResponse {
Login = login;
UserName = userName;
GroupAccess = groupAccess};
},
splitOn: "UserNameId,GroupId",
param: new
{
Id = request.IdEmployee
}
).FirstOrDefault();

A better way to combine two Linq Queries into one in MVC5 Controller

in my MVC Application using EntityFramework I have a self referencing table: customers with customerParentID. For children with no emails I want to be able to channel correspondence to parents Email. This is the solution I have that works but I am hitting database 3 times and I want to combine the last 2 into one.
Controller Linq Query
useParentEmail is a bool which is true for children with no Email
Id is obtained by a parameter
var b = db.Lists.SingleOrDefault(a => a.LatestTxnId == Id);
var customerWithNoEmail = db.Customers.SingleOrDefault(a => a.CustomerID == b.CustomerID && a.useParentEmail);
if (customerWithNoEmail != null)
{
var customerParent = db.Customers.SingleOrDefault(a => a.CustomerID == customerWithNoEmail.ParentCustomerID);
customerParentEmail = customerParent.Email;
}
This query hits database twice is there a better way I can do this to hit database once? Any help will be appreciated.
Assuming you are using Entity Framework with the correct navigation properties in the model so that joins work automagically, something like this could work (I've used LinqPad and linq to objects for ease of example). To be honest although I used to be a heavy user of Entity Framework I haven't used it for a few years so I could be a little rusty.
var customers = new[]
{
new { CustomerID = 1, useParentEmail = true, email = "", ParentCustomerID = (int?)2 },
new { CustomerID = 2, useParentEmail = false, email = "parent#example.org", ParentCustomerID = (int?)null },
new { CustomerID = 3, useParentEmail = false, email = "child#example.org", ParentCustomerID = (int?)null }
};
int id = 1;
var emails = (from c in customers
join p in customers on c.ParentCustomerID equals p.CustomerID into childrenParents
from cp in childrenParents.DefaultIfEmpty()
where c.CustomerID == id
select new
{
c.CustomerID,
email = c.useParentEmail == true ? cp.email : c.email
}).SingleOrDefault();
emails.Dump();

Lua - Insert table values

I got a table of form let's say:
house = {
["Street 22"] = {
{name = "George", age = 20},
{name = "Pete", age = 25}
},
["Street 30"] = {
{name = "John", age = 32},
}
}
And I want to insert programmatically a third house, that is key "Street 35", with a person's details, Nick and 30 let's say. I am relatively new to lua and don't know how to do this, I must use table.insert but I am having troubles following the above format... Some help please?
Do it simple so:
house["Street 52"] = {{name = "Nick", age = 30}}
You could also mutate the third element of the houses table like this:
house[3]={name = "Nick", age = 30}
did you read this and get confused?
just try table.insert(house, {name = "Nick", age = 30}) and house[3] now contains the new element.

Count books of user with Linq-To-Sql

I'm new in linq and i have a simple problem.
i must count how many books have user.
i know its easy but i cant do this.
//database
public List<UserViewModel> GetAllUsers()
{
var result = from u in databaseContext.User
select new UserViewModel
{
UserId = u.UserId,
LastName = u.LastName,
FirstName = u.FirstName,
BirthDate = u.BirthDate,
Email = u.Email,
Phone = u.Phone,
AddDate = u.AddDate,
ModifiedDate = u.ModifiedDate,
IsActive = u.IsActive,
};
return result.ToList();
}
how to do this?
In your model it seems that every Borrow has exactly one Book associated with it. If that is the case and the books cannot be taken more than once (which should be also correct) then all you need to do is:
int count = context.Users.First(x=>x.UserId = 1).Borrow.Count();
This way you can count all the Borrows of a given user supposing that they are all associated with a book.
If two borrows can have the same book than you should slightly rewrite this query to this:
int count = db.Borrow.Where(x => x.UserID== 1).Select(x => x.BookId).Distinct().Count();
This way you will get only the unique books borrowed from the user with id of 1.
To count only the unique books that are not returned use this:
int count = db.Borrow.Where(x => x.UserID== 1 && x.IsReturned == false).Select(x => x.BookId).Distinct().Count();

Adapting Linq Entity objects to Domain objects

I have the following code which adapts linq entities to my Domain objects:
return from g in DBContext.Gigs
select new DO.Gig
{
ID = g.ID,
Name = g.Name,
Description = g.Description,
StartDate = g.Date,
EndDate = g.EndDate,
IsDeleted = g.IsDeleted,
Created = g.Created,
TicketPrice = g.TicketPrice
};
This works very nicely.
However I now want to populate a domain object Venue object and add it to the gig in the same statement. Heres my attempt....
return from g in DBContext.Gigs
join venue in DBContext.Venues on g.VenueID equals venue.ID
select new DO.Gig
{
ID = g.ID,
Name = g.Name,
Description = g.Description,
StartDate = g.Date,
EndDate = g.EndDate,
IsDeleted = g.IsDeleted,
Created = g.Created,
TicketPrice = g.TicketPrice,
Venue = from v in DBContext.Venues
where v.ID == g.VenueID
select new DO.Venue
{
ID = v.ID,
Name = v.Name,
Address = v.Address,
Telephone = v.Telephone,
URL = v.Website
}
};
However this doesnt compile!!!
Is it possible to adapt children objects using the "select new" approach?
What am I doing so very very wrong?
Your inner LINQ query returns several objects, not just one. You want to wrap it with a call like:
Venue = (from v in DBContext.Venues
where v.ID == g.VenueID
select new DO.Venue
{
ID = v.ID,
Name = v.Name,
Address = v.Address,
Telephone = v.Telephone,
URL = v.Website
}).SingleOrDefault()
Your choice of Single() vs. SingleOrDefault() vs. First() vs. FirstOrDefault() depends on what kind of query it is, but I'm guessing you want one of the first two. (The "OrDefault" variants return null if the query has no data; the others throw.)
I also agree with Mike that a join might be more in line with what you wanted, if there's a singular relationship involved.
Why are you doing a join and a sub select? You can just use the results of your join in the creation of a new Venue. Be aware that if there is not a one to one relationship between gigs and venues you could run into trouble.
Try this:
return from g in DBContext.Gigs
join venue in DBContext.Venues on g.VenueID equals venue.ID
select new DO.Gig { ID = g.ID, Name = g.Name, Description = g.Description,
StartDate = g.Date, EndDate = g.EndDate, IsDeleted = g.IsDeleted,
Created = g.Created, TicketPrice = g.TicketPrice,
Venue = new DO.Venue { ID = venue.ID, Name = venue.Name,
Address = venue.Address, Telephone = v.Telephone,
URL = v.Website }

Resources