如何使用neo4jclient查询连接图,如EF中的Master detail SQL

时间:2013-08-12 03:03:30

标签: neo4jclient

我是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&amp; 22寄售1的第11项和第11项。 12。

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

此致 基兰

1 个答案:

答案 0 :(得分: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)表示您知道货件ID。

因此,我们可以稍微简化一下代码 - 因为我们不需要使用'root',我们可以传递货件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; } }
}

(需要时会有明显的变化)