Has anyone figured out a solution for when you're running a query but are expecting multiple labels to be returned?
For example, say I have the following query to return all persons associated with a Movie
:
MATCH (movie:Movie)-[link]->(person)
WHERE movie.Title = "The Princess Bride"
RETURN person;
person
could be a Director
, Actor
, Producer
, or some other label in the database, but the results don't tell me that, nor does there appear to be a way to figure that out within the query (other than using Labels()
).
I have classes defined for each of those labels that specify the fields I'm expecting so I can perform various operations on them, but I'm not sure how to use Neo4jClient to resolve those types.
Currently I've just been doing the following:
IEnumerable<Actor> actorResult = this._graphClient.Cypher
.Match("(movie:Movie)-[link]->(person:Actor)")
.Where((Movie movie) => movie.Title == "The Princess Bride")
.Return((person) => person.As<Actor>())
.Results;
And repeating that for each label (replacing the label/types appropriately), but three queries is obviously not ideal when you can just as easily do it in one. I was thinking I could collect the label(s) of the node, loop through the results, and cast based on that, but it's a lot of extra work that didn't end up working; I would still need to be able to cast from object
to my defined types.
I may be completely overthinking this one, but I appreciate any suggestions.
You always have to do some deserialization if you're going to be pulling multiple types from one query, it is doable, but as to whether it's more performant? That's going to take some testing - Personally - I would think it is better to do the deserializing in code vs 3x calls to the DB.
This is a very basic example, but it should get you there:
var query = _graphClient.Cypher
.Match("(movie:Movie)-[link]->(person)")
.Where((Movie movie) => movie.Title == "The Princess Bride")
.Return(person => new {
Node = person.As<Node<string>>(),
Labels = person.Labels()
});
var actors = new List<Actor>();
var directors = new List<Director>();
foreach(var person in query.Results)
{
if(person.Labels.Contains("Actor")
actors.Add(JsonConvert.DeserializeObject<Actor>(person.Node.Data));
if(person.Labels.Contains("Director")
directors.Add(JsonConvert.DeserializeObject<Director>(person.Node.Data));
/* ETC */
}