加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何在Neo4j v2中创建Neo4jClient的节点?

发布时间:2020-12-15 06:35:49 所属栏目:百科 来源:网络整理
导读:在Neo4j v1.9.x下,我使用了以下代码. private Category CreateNodeCategory(Category cat){ var node = client.Create(cat,new IRelationshipAllowingParticipantNodeCategory[0],new[] { new IndexEntry(NeoConst.IDX_Category) { { NeoConst.PRP_Name,cat.
在Neo4j v1.9.x下,我使用了以下代码.
private Category CreateNodeCategory(Category cat)
{
        var node = client.Create(cat,new IRelationshipAllowingParticipantNode<Category>[0],new[]
            {
                new IndexEntry(NeoConst.IDX_Category)
                {
                    { NeoConst.PRP_Name,cat.Name },{ NeoConst.PRP_Guid,cat.Nguid.ToString() }
                }
            });
        cat.Nid = node.Id;
        client.Update<Category>(node,cat);
        return cat;
}

原因是节点ID是自动生成的,我可以稍后使用它来快速查找,在其他查询中启动位等.如下所示:

private Node<Category> CategoryGet(long nodeId)
    {
        return client.Get<Category>((NodeReference<Category>)nodeId);
    }

这使得以下可以正常工作.

public Category CategoryAdd(Category cat)
    {
        cat = CategoryFind(cat);
        if (cat.Nid != 0) { return cat; }
        return CreateNodeCategory(cat);
    }

    public Category CategoryFind(Category cat)
    {
        if (cat.Nid != 0) { return cat; }
        var node = client.Cypher.Start(new { 
    n = Node.ByIndexLookup(NeoConst.IDX_Category,NeoConst.PRP_Name,cat.Name)})
            .Return<Node<Category>>("n")
            .Results.FirstOrDefault();
        if (node != null) { cat = node.Data; }
        return cat;
    }

现在,cypher Wiki,示例和不良习惯建议在所有CRUD中使用.ExecuteWithoutResults().

所以问题是如何对节点ID进行自动增量?

解决方法

首先,对于Neo4j 2及以上,您始终需要从参考框架开始:“我如何在Cypher中做到这一点?”.那么,只有这样,你担心C#.

现在,提炼你的问题,这听起来像你的主要目标是创建一个节点,然后返回一个引用来进一步的工作.

你可以在cypher中做到这一点:

CREATE (myNode)
RETURN myNode

在C#中,这将是:

var categoryNode = graphClient.Cypher
    .Create("(category {cat})")
    .WithParams(new { cat })
    .Return(cat => cat.Node<Category>())
    .Results
    .Single();

但是,这仍然不是您原始CreateNodeCategory方法中的100%.您正在创建DB中的节点,获取Neo4j的内部标识符,然后将该标识符保存回同一个节点.基本上,您正在使用Neo4j为您生成自动递增的数字.这是功能,但不是一个很好的方法.我会解释更多…

首先,Neo4j的概念甚至给你节点id回来已经消失了.这是一个内部标识符,实际上恰好是磁盘上的文件偏移量.它可以改变是低水平如果您再次考虑SQL,您是否使用SQL查询来获取一行的文件字节偏移量,然后参考以供将来更新? A:不你写一个查询,可以在一个命中中找到并操纵该行.

现在,我注意到你已经在节点上有一个Nguid属性.为什么你不能用它作为id?或者如果名称总是独一无二的,那么使用? (域名相关的ID总是比魔术数字更好.)如果两者都不合适,可能需要查看像SnowMaker这样的项目来帮助你.

接下来,我们需要看索引.您使用的索引类型在2.0文档中被称为“Legacy Indexing”,并忽略了一些酷炫的Neo4j 2.0功能.

对于这个答案的其余部分,我将假设你的Category类看起来像这样:

public class Category
{
    public Guid UniqueId { get; set; }
    public string Name { get; set; }
}

我们开始创建一个label的类别节点:

var category = new Category { UnqiueId = Guid.NewGuid(),Name = "Spanners" };
graphClient.Cypher
    .Create("(category:Category {category})")
    .WithParams(new { category })
    .ExecuteWithoutResults();

而且,作为一次性操作,让我们建立一个schema-based index的名称属性的任何节点与类别标签:

graphClient.Cypher
    .Create("INDEX ON :Category(Name)")
    .ExecuteWithoutResults();

现在,我们不用担心手动保持索引的最新.

我们还可以在UniqueId上引入索引和unique constraint:

graphClient.Cypher
    .Create("CONSTRAINT ON (category:Category) ASSERT category.UniqueId IS UNIQUE")
    .ExecuteWithoutResults();

查询现在很容易:

graphClient.Cypher
    .Match("(c:Category)")
    .Where((Category c) => c.UniqueId == someGuidVariable)
    .Return(c => c.As<Category>())
    .Results
    .Single();

而不是查找一个类别节点,然后再做另一个查询,只需一下子就行:

var productsInCategory = graphClient.Cypher
    .Match("(c:Category)<-[:IN_CATEGORY]-(p:Product)")
    .Where((Category c) => c.UniqueId == someGuidVariable)
    .Return(p => p.As<Product>())
    .Results;

如果您想要更新类别,请另行进行:

graphClient.Cypher
    .Match("(c:Category)")
    .Where((Category c) => c.UniqueId == someGuidVariable)
    .Update("c = {category}")
    .WithParams(new { category })
    .ExecuteWithoutResults();

最后,您的CategoryAdd方法目前是1)一个DB命中找到现有的节点,2)第二个DB命中创建一个新的,3)第三个DB命中来更新它上的ID.相反,您可以使用MERGE keyword将所有这些压缩到单个呼叫:

public Category GetOrCreateCategoryByName(string name)
{
    return graphClient.Cypher
        .WithParams(new {
            name,newIdIfRequired = Guid.NewGuid()
        })
        .Merge("(c:Category { Name = {name})")
        .OnCreate("c")
        .Set("c.UniqueId = {newIdIfRequired}")
        .Return(c => c.As<Category>())
        .Results
        .Single();
}

基本上,

>不要使用Neo4j的内部ids作为一种方式来管理自己的身份. (但是他们可能会在以后发布某种形式的自动编号,即使是这样,域名身份如电子邮件地址或SKU或机场代码或…是首选,您甚至不需要一个id:你可以经常推断节点根据其在图中的位置.)
通常,Node< T>随着时间的推移会消失.如果你现在使用它,你只是累积了旧代码.
>查看标签和基于模式的索引.他们将使你的生活更轻松.
>在一个查询中尝试和做事情.这会快得多

希望有帮助!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读