Search code examples
c#neo4jcypherneo4jclient

Combining return values into a single type


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:

  • Title
  • Body
  • LanguageCode

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?


Solution

  • 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.