Search code examples
neo4jneo4jclient

Problems adding new property to existing node with Neo4jClient


My beginner problems with using Neo4jClient unfortunately continues :) I have a simple class WorkEntity for which I have an update query:

public class WorkEntity
{
    public string Id { get; set; }
    public string Description { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
}

var query = graphClient.Cypher
            .Match("(work:Work)", "(city:City)", "(profession:Profession)", "(company:Company)", "(oldCompany:Company)", "(oldProfession:Profession)", "(oldCity:City)",
            "(user:User)-[r1]->work", "work-[r2]->oldProfession", "work-[r3]->oldCompany", "work-[r4]->oldCity")
            .Where((WorkEntity work) => work.Id == model.Id)
            .AndWhere((CityEntity city) => city.Id == model.CityId)
            .AndWhere((CityEntity oldCity) => oldCity.Id == oldModel.CityId)
            .AndWhere((ProfessionEntity profession) => profession.Id == model.ProfessionId)
            .AndWhere((ProfessionEntity oldProfession) => oldProfession.Id == oldModel.ProfessionId)
            .AndWhere((CompanyEntity company) => company.Id == model.CompanyId)
            .AndWhere((CompanyEntity oldCompany) => oldCompany.Id == oldModel.CompanyId)
            .AndWhere("type(r1) = 'CURRENT'")
            .AndWhere("type(r2) = 'WORK_AS_PROFESSION'")
            .AndWhere("type(r3) = 'WORK_AT_COMPANY'")
            .AndWhere("type(r4) = 'WORK_IN_CITY'")
            .Set("work = {updatedWork}")
            .WithParam("updatedWork", updatedEntity);

        //If Date has been set delete current relationships
        if (oldModel.EndDate == DateTime.MinValue && model.EndDate > DateTime.MinValue)
        {
            query = query.Delete("r1");
        }
        if (oldModel.ProfessionId != model.ProfessionId)
        {
            query = query.Delete("r2")
                .CreateUnique("work-[:WORK_AS_PROFESSION]->profession");
        }
        if (oldModel.CompanyId != model.CompanyId)
        {
            query = query.Delete("r3")
                .CreateUnique("work-[:WORK_AT_COMPANY]->company");
        }
        if (oldModel.CityId != model.CityId)
        {
            query = query.Delete("r4")
               .CreateUnique("work-[:WORK_IN_CITY]->city");
        }

        query.ExecuteWithoutResults();

Modifying all the relationsships works as expected but if for example Description is null from the beginning above query won't add Description to an existing entity (or update any other of the properties) even though it is set in updatedEntity. If I simplify the query as below Description is added/removed and existing changed properties are updated correctly. How can that be? I really would prefer to do the whole query in one transaction.

 var query = graphClient.Cypher
            .Match("(work:Work)")
            .Where((WorkEntity work) => work.Id == model.Id)
            .Set("work = {updatedWork}")
            .WithParam("updatedWork", updatedEntity);

Solution

  • Thanks Chris, I realise that my understanding for Neo4j is still quite limited :) Your suggestion above updates the work entity properties correctly but not the relationsships. I don't really get why the work-[r4]-oldCity relationship doesn't match anything but anyway I took advantage of your note about this and after some trial and error finally got the query to work correctly like:

            var oldModel = GetWorkModel(model.Id);
            var updatedEntity = Mapper.Map<WorkEntity>(model);
    
            var query = graphClient.Cypher
                .Match("(work:Work)", "(city:City)", "(profession:Profession)", "(company:Company)",
                    "(user:User)-[r1:CURRENT]->work", "work-[r2:WORK_AS_PROFESSION]->()", "work-[r3:WORK_AT_COMPANY]->()", "work-[r4:WORK_IN_CITY]->()")
                .Where((WorkEntity work) => work.Id == model.Id)
                .AndWhere((CityEntity city) => city.Id == model.CityId)
                .AndWhere((ProfessionEntity profession) => profession.Id == model.ProfessionId)
                .AndWhere((CompanyEntity company) => company.Id == model.CompanyId)
                .Set("work = {updatedWork}")
                .WithParam("updatedWork", updatedEntity);
    
            if (oldModel.EndDate == DateTime.MinValue && model.EndDate > DateTime.MinValue)
                query = query.Delete("r1");
            if (oldModel.ProfessionId != model.ProfessionId)
                query = query.Delete("r2").CreateUnique("work-[:WORK_AS_PROFESSION]->profession");
            if (oldModel.CompanyId != model.CompanyId)
                query = query.Delete("r3").CreateUnique("work-[:WORK_AT_COMPANY]->company");
            if (oldModel.CityId != model.CityId)
                query = query.Delete("r4").CreateUnique("work-[:WORK_IN_CITY]->city");
    
            query.ExecuteWithoutResults();