使用Neo4jClient向现有节点添加新属性时出现问题

时间:2014-02-26 12:39:46

标签: neo4j neo4jclient

我的初学者使用Neo4jClient时遇到的问题很遗憾:)我有一个简单的类WorkEntity,我有一个更新查询:

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();

修改所有关系都按预期工作,但是如果例如说明从上面开始为null,则查询将不会将描述添加到现有实体(或更新任何其他属性),即使它是在updatedEntity中设置的。如果我简化查询,则添加/删除描述,并正确更新现有更改的属性。怎么可能?我真的更愿意在一次交易中完成整个查询。

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

2 个答案:

答案 0 :(得分:2)

我认为,当CityId s在我的要点中是相同的时,查询无效的原因是因为MATCH子句:

work-[r4]-oldCity

不匹配任何内容,因此匹配失败,查询不执行任何操作。

实际上 - 如果我做对了 - 你正在尝试两个查询:

  1. 更新work
  2. 删除&创建新关系
  3. 我认为您应该查看WITH关键字,因为它应该有助于您的查询......

    WITH允许您将密码查询链接在一起,因此您可以将查询更改为:

    var query = Client.Cypher
        .Match("(work:Work)")
        .Where((WorkEntity work) => work.Id == model.Id)
        .Set("work = {updatedWork}")
        .With("work")
        .Match("(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'")
        .WithParam("updatedWork", updatedEntity);
    

    这将执行更新,然后执行其余操作。

    可能值得一看的另一个关键字是MERGE,但我认为WITH可以帮助你。

答案 1 :(得分:0)

谢谢Chris,我意识到我对Neo4j的理解仍然非常有限:)上面的建议正确地更新了工作实体属性,但没有更新关系。我真的不明白为什么工作 - [r4] -oldCity关系不匹配任何东西,但无论如何我利用你关于这个的说明,经过一些试验和错误终于让查询正常工作,如:

        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();