I have a Neo4j relationship that looks like this:
(a:Article)<-[:TRANSLATES]-(t:ArticleTranslation)
The Article
label is applied to nodes which simply hold a unique identifier and the ArticleTranslation
label is applied to nodes which contain:
I then have an ICypherFluentQuery
that is constructed like so:
Match("(t:ArticleTranslation)-[:TRANSLATES]->(a:Article)")
.Where("(a.Id = {id})")
.AndWhere("(t.LanguageCode = {lang} OR (t.LanguageCode = 'en' and NOT a<--(:ArticleTranslation { LanguageCode: {lang} })))")
.WithParams(new { id, lang })
From here, I understand that I can easily map (a, t)
to an anonymous object containing two object instances such as:
new { Article = new Article { /* Article Properties */ },
Translation = new ArticleTranslation { /* Translation Properties */ } }
However, in my application it is more useful (and intuitive) to work with both "article" and "translation" as a single entity, e.g.:
public class Article
{
public string Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string LanguageCode { get; set; }
}
I have managed to do this by adding the following:
.Return((a, t) => new Article
{
Id = a.As<Article>().Id,
Title = t.As<Article>().Title,
Body = t.As<Article>().Body,
LanguageCode = t.As<Article>().LanguageCode
});
However, this is unwieldy (especially when increasing the number of properties) and looks like it may invoke repeated mappings.
Is there a more succinct way of expressing this without introducing an independent ArticleTranslation
entity?
You can tell Neo4jClient to generate an arbitrary Cypher RETURN
statement - and map it to the desired type - by passing in a parameterless delegate:
.Return(() => Return.As<ArticleTranslation>(
"{ArticleId:a.Id, Title:t.Title, Body:t.Body, LanguageCode:t.LanguageCode}"))
In this example, the literal map is returned and then mapped to the ArticleTranslation
type by Neo4jClient.