3

So I have some code that performs a Neo4j cypher query that returns an IEnumerable of type FolderObject like so:

public IEnumerable<FolderObject> GetChild(string parentId)
{
    IEnumerable<FolderObject> childNode = null;
    var query = GraphConnection.Cypher
    .Start(new { n = Node.ByIndexLookup("node_auto_index", "ObjectId", parentId) })
    .Match("(n)-[r:HAS_FOLDER]->(b)")
    .Where("b.ParentId = n.ObjectId")
    .Return<FolderObject>("b");

    childNode = query.Results;

    return childNode;
}

FolderObject looks like so:

public string ObjectId { get; set; }
public string ParentId {get; set;}
public List<GraphObject> Children { get; set; }

Then I have this method which works fine:

public List<FolderObject> GetChildren(string repositoryId, string folderId)
{
    List<FolderObject> items;

    QueryOperations query = new QueryOperations(GraphConnection);

    var queryResult = query.GetChild(folderId);

    string childId = null;

    if (queryResult != null)
    {
        foreach (var item in queryResult)
        {
            childId = item.ObjectId;

            items = new List<FolderObject>();

            items.Add(item);

            var nextChild = GetChildren(repositoryId, childId);
        }
    }
    else
    {
        throw new Exception("The Folder with Id: " + folder + " could not be found.");
    }

    return items
}

Now the problem comes when I try and do this recursively. What I need to do is get the top most folder add that to a list then get the next folder below the top most and add that in as a child. Then repeat until there are no more children.

The structure as follows:

-Folder
    -Folder
        -Folder
            -Folder

and return this structure as a List?

Here is the Json

{
    "ParentId": "0",
    "ObjectId": "1",
    "children": [
        {
            "ParentId": "1",
            "ObjectId": "2",
            "children": [
                {
                    "ParentId": "2",
                    "ObjectId": "3"
                }
            ]
        }
    ]
}
Tatham Oddie
  • 4,290
  • 19
  • 31
Mike Barnes
  • 4,217
  • 18
  • 40
  • 64
  • 1
    Writing "node:node_auto_index(ObjectId = '" + parentId + "')" is a great way to allow a Cypher injection attack. Please use Node.ByIndexLookup instead: it will protect you against this. – Tatham Oddie Oct 16 '13 at 22:32

1 Answers1

2

You could use a Stack<FolderObject> which is similar to a recursive method, the only difference is that it's not recursive. Imho it's more readable and less complex.

public List<FolderObject> GetChildren(string repositoryId, string folderId)
{
    List<FolderObject> items = new List<FolderObject>();;

    QueryOperations query = new QueryOperations(GraphConnection);
    var queryResult = query.GetChild(folderId);

    Stack<FolderObject> folders = new Stack<FolderObject>(queryResult);

    while (folders.Count > 0)
    {
        FolderObject currentFolder = folders.Pop();
        var childId = currentFolder.ObjectId;
        items.Add(currentFolder);
        var nextChildren = GetChildren(repositoryId, childId);
        foreach (FolderObject child in nextChildren)
            folders.Push(child);
    }

    return items;
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Thanks but does it matter if the query only returns one result? – Mike Barnes Oct 16 '13 at 08:27
  • 1
    @MikeBarnes: No, since the loop stops not before the stack is empty and it doesn't matter if the `foreach` adds none, one or a million folders. – Tim Schmelter Oct 16 '13 at 08:31
  • Thanks for the help gonna give it a try now! – Mike Barnes Oct 16 '13 at 08:32
  • @MikeBarnes: Note that i've only just removed your `items = new List();` from the loop since it would always clear the list in the loop which is pointless. It's possible that there are other bugs since the code is untested but i think you get the idea. – Tim Schmelter Oct 16 '13 at 08:33
  • Is the structure still in place? – Mike Barnes Oct 16 '13 at 08:37
  • Should you not instantiate the `List items=new List();` at the beginning? – Mike Barnes Oct 16 '13 at 08:41
  • @MikeBarnes: Note that i've changed the `while` loop condition and instantiated the list. The structure/order in the list should remain. Try it out. – Tim Schmelter Oct 16 '13 at 08:43
  • It works fine, however it returns 22 items in the array whereas there should only be 3? The rest are duplicates? It looks like 12232222..... and so on, it should be 123. Im just using 1, 2, 3 as id's – Mike Barnes Oct 16 '13 at 08:51
  • And how would I understand the structure rather? – Mike Barnes Oct 16 '13 at 08:54
  • @MikeBarnes: I assume that's a bug because i have added `queryResult` to the constructor of the stack **and** in the `foreach`-loop afterwards. Remove the `foreach` just before the `while`-loop. Edited my answer. – Tim Schmelter Oct 16 '13 at 08:58
  • Ok that made it better, but I think i should edit my question and add in the json that needs to be created in that folder structure? – Mike Barnes Oct 16 '13 at 09:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/39334/discussion-between-mike-barnes-and-tim-schmelter) – Mike Barnes Oct 16 '13 at 09:36