Dataview searches on all outgoing notes

Can I do dataview searches on a local graph?

Say I have this local graph:


(outgoing notes from note [[0]])

I want to find these notes with dataview.

I can type:
TABLE file.name FROM outgoing([[0]])

But this search will only return the nearest neighbours of note [[0]] (i.e. [[1a]], [[1b]] and [[1c]])

I want the search to also return [[2a]] and [[2b]]

Is there a way to do this?
Sure, I could add a metadata field in all the outgoing notes of [[0]] (in order to filter then in dataview) but this seems very tedious.

Thanks

4 Likes

Ooooh recursion, how fun! (Recursion is one of the tougher topics in many computer science or programming courses but you have an excellent example right here for thinking through the concepts, thank you for sharing!)

I don’t know how to do this in the dataview query language (DQL) but if you’re willing to try Javascript there’s an example very similar to what you are looking for on the codeblock examples page in the documentation. That example is looking at incoming links as well as outgoing, though, so you’ll want to modify it a bit. That’s what the rest of this post is about. You also might consider looking at additional community plugins such as “Breadcrumbs” or things under the search term “MOC” in the plugin search to see if any will just do what you want!

Commented code from the example, which searches incoming links
This would go in a dataviewjs codeblock instead of the dataview one you are currently using. You might need to enable javascript queries in your dataview settings. The symbols /* and */ start and end a comment, respectively, in Javascript, so you can delete or write anything inside them without changing the functionality of the code. Some of the comments below were written by the author of the dataview documentation and some by me.

let page = dv.current().file.path;
let pages = new Set();
let stack = [page]; /* everything to do with stack is the bit I have no idea how to do in regular DQL */
while (stack.length > 0) {
    let elem = stack.pop();
    let meta = dv.page(elem);
    if (!meta) continue; /* ignore links to pages that don't exist yet */

    for (let inlink of meta.file.inlinks.concat(meta.file.outlinks).array()) {
        /*console.log(inlink);*/
        if (pages.has(inlink.path)) continue; /* only look at pages we haven't seen yet, otherwise we could get stuck following circular links forever */
        pages.add(inlink.path);
        stack.push(inlink.path);
    }
}

/* Data is now the file metadata for every page that directly OR indirectly links TO the current page. */
let data = dv.array(Array.from(pages)).map(p => dv.page(p));

/* Display the table. The part with quotes is a list  - indicated by the single [ ] around it, which mean list or array in JS - of your column names, like if you used AS in a dataview query, so change them however you like. 
The part after "(p =>" is a list of the stuff you want in your columns. 
I tried to match what I think your TABLE example from your post would do. */
dv.table(["File Link", "file.name"], data.map(p => [p.file.link, p.file.name]));

Modifying the example
You want to know about outgoing links (aka “outlinks”) not incoming links.
So we want to change the part of the code that starts with for.

    for (let linkedFile of meta.file.outlinks.array()) {
        /*console.log(linkedFile);*/
        if (pages.has(linkedFile.path)) continue; /* only look at pages we haven't seen yet, otherwise we could get stuck following circular links forever */
        pages.add(linkedFile.path);
        stack.push(linkedFile.path);
    }

I recommend hand modifying your lines of code rather than copy-pasting this in so that you know it’s still in the right place with respect to the } at the end of the while loop.

Does this work for you?
Good luck, please let me know if I can clarify anything! This was a lot of code for a short question. :slight_smile:

3 Likes

@scholarInTraining

Hello! Trying to implement the snippet you provided, but running into a type error. When trying to render with

dv.table(["File Link", "file.name"], data.map(p => [p.file.link, p.file.name]));

as typed above included in the code, I see the following:

Evaluation Error: TypeError: Cannot read properties of undefined (reading 'file') at...

It looks to me like the array data of linked files is being generated successfully, but that I’m having trouble understanding the syntax for rendering any kind of output from that array.

Ultimately what I’d like to do is generate a task list containing all tasks on pages that link directly/indirectly to the current page. I’ve tried to implement that in a few ways, including:

dv.taskList(data.file.tasks, groupByFile);

but seeing the same type error described above. How can I go about troubleshooting this? Apologies if I’m missing something basic, it has been some time since I’ve used Javascript regularly.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.