How to automatically create links between note2 and note3 **in note 1**

Hi, im trying to build some sort of timeline graph in obsidian.
When there is a person x in note2 and an item y in note3, they are not linked until some event(note1) happens.
So, i don’t want to create link between x and y initially, i want to create it when somethink happens, e.g., when i open the note1, or i click the button in note1, etc.

Is there any method to do so? I have tried dataview, text expander, templater, breadcrumbs and juggl, but still have no idea.

I think you need to provide some more information. Why should a random open of a note trigger a link between a random person note, and a random item note?

How and why do you want the person and item to be connected?

And what do you know of those plugins (and/or javascript)?

Re-reading the title of your question, it seems like you want to make a direct link from Note2 to Note3, using only notation in Note1. That’s not (easily) doable.

Dual links in Note1

You can link to both Note2 and Note3 from Note1, and as such kind of create a link between these two. And if you want that kind of relation I would strongly suggest using lists to keep the links in the same scope.

In other words do something like the following in Note1:

- [[Note2]] owns multiple [[Note3]]

This will not show up directly as a link between Note2 and Note3, but it’s possible to make these links show in a dataview query later on.

Javascript in Note1

There is also a possibility to have a button in Note1 which triggers some javascript which changes the content of either Note2 or Note3 (or both).

This would require some javascript knowledge, a button (or trigger) and some logic to choose which person to connect to which item. And possibly some defined structure within Note2 and Note3 related to placing the new links at a given place.

I don’t think this is something any plugin I know would do out of the box. Maybe with the exception of something like Database folders, which I’ve not used. All the other plugins you mention are mostly for reading/querying data, not writing data into other files.

And I believe those dual links that holroy describes can be shown in the local graph by setting how many links away to show (I don’t know the actual terminology; I don’t use the local graph myself).

Thanks, thats what im doing right now. I use breadcrumbs to temporarily solve this. In the “event” note 1, i write these in yaml front-matter:

---
persons:
 - [[x]]
items:
 - [[y]]
---

And it will create link graph in breadcrumbs as person----event----item.

i don’t understand you said

but it’s possible to make these links show in a dataview query later on.

I write

event:: [x](note2.md) owns [y](note3.md) 

in note 1, similar as you said.

But when i use dataview query, it only show note2 and note3 as links to the query page.
How to query from list and how to use dataview to show links between note2 and note3? Thanks!

Sorry for the delay in my answer, but I want to give you a proper answer, with some examples, because you’re touching in on various key concepts, which can make it a lot harder or easier for you depending on the syntax you choose.

Field definitions in frontmatter

As I understanding it you’re aiming to group some information together to create a relationship (or link) between various other notes. Using the syntax you provided, you’re creating two disconnected lists. Or for the event:: definition it’s just a string, with actually no links stored (or queryable).

A better option if using the frontmatter I think would be to keep the relationship information together within one objects, so something like the following could work:

---
Tags: f55889
events:
- primary: "[[Note2]]"
  relation: "owns"
  secondary: "[[Note3]]"
- primary: "[[John]]"
  relation: "owns"
  secondary: "[[Xbox]]"
---

This defines one field, events, which is a list of all those starting with -, where each of those again have the fields: primary, relation and secondary. A query displaying these values from the same note:

```dataview
TABLE WITHOUT ID E.primary, E.relation, E.secondary
FLATTEN events as E
WHERE file.name = this.file.name
```

Results in this output:

I’m using the FLATTEN events as E to split up events into its single events, and then display these. Names can of course be altered according to your will.

The downside of doing it this way, is that the links are not actually treated as links, so there will be no connection between Note2 and Note1 (given the query was in Note1), nor between Note3 and Note1. So no backlinks, and if you rename either note, it’ll not be propagated, and so on.

The plus side of this variant, could be some of the same arguments if that suits your needs, and in addition it’s kind of a clear markup. It can be changed into various similar markups, this is just the way I prefer to do this particular style of lists of objects in the frontmatter

Currently dataview doesn’t allow for list of objects to be defined outside of the frontmatter (or YAML). This is something which seemingly will be addressed in the new datacore plugin, if or when that is ready for us to use.

Using lists

However, I’m preferring to use lists for this kind of markup in most cases, as it allows me to see the linked text, and if formatted properly, I kind of like seeing the definitions.

So here is another example you could try in a note of its own:

## Using lists

- [[Note2]] (relation:: owns) [[Note3]]
- [[John]] (relation:: owns) [[Xbox]], [[Nintendo Switch]]

```dataview
TABLE WITHOUT ID item.outlinks[0], item.relation, item.outlinks[1]
FLATTEN file.lists as item
WHERE relation
```

## With multiple secondary relations...
```dataview
TABLE WITHOUT ID item.outlinks[0], item.relation, filter(item.outlinks, (i) => i != item.outlinks[0])
FLATTEN file.lists as item
WHERE relation
```

In my setup this displays as:

Sorry for the non-defined links which is a little dark, but you get the gist of it.

What I like about this setup is that I’m using the field relation to help me detect which notes do have some relation between notes. I then use two implicit connections, where the first link in the list item is considered the origin/primary part of the relation, and any other links are considered secondary to the relation.

This scheme then allows for multiple kind of relations to be created. You could easily create relations like relatives, or ownership, or work relations, or whatever you can think of. Given proper formatting, you can also extend the sentences to make them more meaningful, but still be queryable using the same kind of scripts.

Imagine something like the following:

- [[John]] is the (relation:: father) of [[Mary]], [[Susan]] and [[Robert]]
- [[John]] (relation:: owns) an [[XBox]], [[Nintendo Switch]]
- [[Peter]] is the (relation:: boss)) of [[John]]

Given similar setup across your vaults, you could now write queries where you specify which relation you’re looking for, and pull out who has which part of the relation according to the query above.

For example you could do something like this to check who is a father stuff in your vault:

```dataview
LIST WITHOUT ID item.outlinks[0]
FLATTEN file.lists as item
WHERE item.relation = "father" 
```

Using a similar query you could check who owns an XBox, (which does get a little hairier as we need to do some trickery to keep the rest of the links as an item list.

```dataview
TABLE WITHOUT ID owner, ownedItems
FLATTEN file.lists as item
FLATTEN item.outlinks[0] as owner
FLATTEN array(filter(item.outlinks, (i) => i != item.outlinks[0])) as ownedItems
WHERE relation = "owns" AND contains(ownedItems, [[XBox]])
```

PS: I’ve left all the column headers as they’re defined, but you could of course rename them into something nicer.


In summary, using a list item to contain your related information opens up for easy querying of information in any given list item. If you then add some fields into that list item, the options are nearly endless. It’s just a matter of defining proper relations and being consistent in how you write stuff.

Sadly though, even though we’re now able to connect notes using the queries, we’re still not seeing direct links between the “Note2” and “Note3” from your original example, but given the relationship is defined in “Note1” there’ll be links from that to the other notes.

And if you choose a type of those connecting nodes it could show in either the local graph and/or global graph views.

2 Likes

Thank you very much for your detailed and sample-rich reply, and I have continued to learn some in the past two days.

About the Field definitions in front-matter

I know about object definition in yaml, but as you mentions, links defined in yaml are problematic. They cannot be clicked, but only be used for queries. Also, to maintain the atomicity of notes, I perfer to contains only one note in one event, although an event may contain multiple people and multiple items.
In this situation, I orginally tried to use filed definitions inline, such as

event:: (person:: [[Note2]]) (relation:: owns) (item:: [[Note3]])

as you mentions,

inline nested definitions is not supported, so I finally gave up this and only wrote

event:: [[Note2]] owns [[Note3]]

in text to keep the link, while also added

---
beginTime:: 2000-00-00
endTime:: 2001-00-00
location:: home
relation:: own
---

in yaml to track relation info.
A query displaying these values is::

```dataviewjs
dv.paragraph(dv.markdownTable(["beginTime", "b.endTime", "b.location", "event"], dv.pages('"20 Card/event"').sort(b => b.beginTime).map(b => [b.beginTime, b.endTime, b.location, b.event])))

this query demonstrates all information I keep, but links are dynamics and can’t be shown in graphs, so I use templaters plugin:

| beginTime| endTime| location | event |
| ---- | ---- | ---- | ---------------- |
<%*
const dv = app.plugins.plugins.dataview.api;
const te = dv.pages('"20 Card/event"').sort(b => b.beginTime)
    .map(b => {
        let beginTime = b.beginTime
        let endTime = b.endTime
        let location = b.location
        let event = b.event
        return `|${beginTime}|${endTime}|${location}|${event}|`
        }).join("\n"); 
tR += te;
%>

The templater do the same query as the dataview, only also to write done the result to the note, so these links can be shown in graph-view. I can then create static table whenever I want.

About Using lists

I didn’t realize that lists could also be queried. Based on your suggestion, I will modified

event:: (person:: [[Note2]]) (relation:: owns) (item:: [[Note3]])

into

 - (person:: [[Note2]]) (relation:: owns) (item:: [[Note3]])

and to use dataviewjs flexibly.

Thank again for your help! I know we aren’t still not able to create links between note2 and note3, I will keep on study javascript to do so.
If things worked, I will provide the method below.

Given this restraint, I would like to also mention how you can utilise the graph view (either local or global) to further enhance the links between stuff, and that is through the use of line: ( ... ) to mark groups.

Given that each of the various notes you’re connecting have a unique identifier like one of the following:

type: person
type: relation
type: item

You could use searches like line: ("type:" person) to identify persons in the graph view, and assign a given color to that group. And doing this for all three variants, you could color the nodes which relates your notes. This in combination with proper naming of the relation notes, that could possibly help you see your relation a little clearer.

This particular search, line: ( ... ) searches for words in a given line, which is rather useful when you don’t have access to the full field definitions as we have within dataview queries. It’s kind of the same, but just a little looser in the syntax.

1 Like

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