1

我是 Neo4jClient 和 Neo4J 的新手,所以不知道如何查询数据并获得像 neo4j 中的数据这样的主细节。让我用一个例子来解释一下:

假设我有一个如下图:

root -[:DEFINES] -> Shipment 1 
                -[:HAS_CONSIGNMENT]->Consignment 1
                            -[:HAS_ITEM]->Load Item 11
                            -[:HAS_ITEM]->Load Item 12
                            -[:HAS_CONSIGNEE]->Consignee 1
                -[:HAS_CONSIGNMENT]->Consignment 2
                            -[:HAS_ITEM]->Load Item 21
                            -[:HAS_ITEM]->Load Item 22
                            -[:HAS_CONSIGNEE]->Consignee 2

现在假设我想获取所有图表来填充我的域模型,如下所示

public class Shipment
{
    public List<Consignment> Consignments {get; set;}
}

 public class Consignment
 {
     public List<LoadItem> LoadItems {get; set;}
     public Consignee ShippedTo {get; set;}
 }

 public class LoadItem
 {
 }

我知道我可能可以构建如下所示的 Cypher 查询如何使用 neo4jclient 检索连接图

query = client.Cypher.Start(new { root = client.RootNode }).
            Match("root-[:DEFINES]->load-[:HAS_CONSIGNMENT]->consignments -[:HAS_ITEM]->loadItem").Match("consignments-[:HAS_CONSIGNEE]->consignee").
            Where((Load load) => load.Id == myId).
            Return(
            (load,consignments, loaditems)=>
            new {
                loadInfo = load.As<Node<Load>>(),
                consignments = consignments.CollectAs<Consignment>(),
                loadItems = loaditems.CollectAs<LoadItem>()
            }); 

但我不确定如何将其转换为表示第二级列表,它让我知道寄售 2 有加载项目 21 和 22,而寄售 1 有第 11 和 12 项。

有人可以帮我理解这是如何工作的,因为我主要在 EF 中工作,并且图形查询对我来说真的很新。

问候基兰

4

1 回答 1

0

对,这就是我的工作方式(我很确定 Tatham 会提供更好的答案 - 所以请稍等)

public static ICollection<Shipment> Get()
{
    var query = GraphClient.Cypher
        .Start(new {root = GraphClient.RootNode})
        .Match(
            string.Format("root-[:{0}]->shipment-[:{1}]-consignments-[:{2}]->loadItem", Defines.TypeKey, HasConsignment.TypeKey, HasItem.TypeKey),
            string.Format("consignments-[:{0}]->consignee", HasConsignee.TypeKey)
        )
        .Return((shipment, consignments, loadItem, consignee) =>
        new
        {
            Shipment = shipment.As<Node<Shipment>>(),
            Consignment = consignments.As<Consignment>(),
            LoadItem = loadItem.CollectAs<LoadItem>(),
            Consignee = consignee.As<Consignee>(),
        });

    var results = query.Results.ToList();
    var output = new List<Node<Shipment>>();

    foreach (var result in results)
    {
        var shipmentOut = output.SingleOrDefault(s => s.Reference == result.Shipment.Reference);
        if (shipmentOut == null)
        {
            shipmentOut = result.Shipment;
            shipmentOut.Data.Consignments = new List<Consignment>();
            output.Add(shipmentOut);
        }

        result.Consignment.LoadItems = new List<LoadItem>();
        result.Consignment.LoadItems.AddRange(result.LoadItem.Select(l => l.Data));
        shipmentOut.Data.Consignments.Add(result.Consignment);
    }

    return output.Select(s => s.Data).ToList();
}

这将为您提供所有货物和寄售货物等。 但是我注意到您这样做:.Where((Load load) => load.Id == myId)这意味着您知道货物编号。

因此,我们可以稍微简化代码——因为我们不需要使用“root”,我们可以传入 Shipment ID。

public static Shipment Get2(NodeReference<Shipment> shipmentNodeReference)
{
    var query = GraphClient.Cypher
        .Start(new {shipment = shipmentNodeReference})
        .Match(
            string.Format("shipment-[:{0}]-consignments-[:{1}]->loadItem", HasConsignment.TypeKey, HasItem.TypeKey), 
            string.Format("consignments-[:{0}]->consignee", HasConsignee.TypeKey)
        )
        .Return((shipment, consignments, loadItem, consignee) =>
        new {
            Shipment = shipment.As<Node<Shipment>>(),
            Consignment = consignments.As<Consignment>(),
            LoadItem = loadItem.CollectAs<LoadItem>(),
            Consignee = consignee.As<Consignee>(),
        });

    var results = query.Results.ToList();

    //Assuming there is only one Shipment returned for a given ID, we can just take the first Shipment.
    Shipment shipmentOut = results.First().Shipment.Data;
    shipmentOut.Consignments = new List<Consignment>();
    foreach (var result in results)
    {
        result.Consignment.ShippedTo = result.Consignee;
        result.Consignment.LoadItems = new List<LoadItem>();
        result.Consignment.LoadItems.AddRange(result.LoadItem.Select(l => l.Data));
        shipmentOut.Consignments.Add(result.Consignment);
    }

    return shipmentOut;
}

为了您的信息,我使用的 DataElements 是:

public class Shipment
{
    public string Id { get; set; }
    public List<Consignment> Consignments { get; set; }
    public override string ToString() { return Id; }
}

public class Consignment
{
    public string Id { get; set; }
    public List<LoadItem> LoadItems { get; set; }
    public Consignee ShippedTo { get; set; }
    public override string ToString() { return Id; }
}

public class Consignee
{
    public string Name { get; set; }
    public override string ToString() { return Name; }
}

public class LoadItem
{
    public string Item { get; set; }
    public override string ToString() { return Item; }
}

关系都定义如下:

public class HasConsignment : Relationship, IRelationshipAllowingSourceNode<Shipment>, IRelationshipAllowingTargetNode<Consignment>
{
    public const string TypeKey = "HAS_CONSIGNMENT";

    public HasConsignment() : base(-1) {}
    public HasConsignment(NodeReference targetNode): base(targetNode) {}
    public HasConsignment(NodeReference targetNode, object data) : base(targetNode, data) {}

    public override string RelationshipTypeKey { get { return TypeKey; } }
}

(在需要时进行明显的更改)

于 2013-08-12T14:39:22.510 回答