Using DQL to search a YAML field for wikilinked text

I have a folder full of notes, each of which represents a person. The filename of each file is that person’s name, and there is also YAML frontmatter that identifies the person, e.g.:

Ralph Smith
---
person: Ralph Smith
aliases: Ralphy Smith
title: Director of Sublimation
---

In the body of each such person note, I am trying to use Dataview DQL syntax to list any meetings on which that person is listed as an attendee. The frontmatter of the meeting notes encodes the attendees like so:

attendees:
  - [[Ralph Smith]]
  - James Nematode

So, the dataview block on each person page currently reads like this:

TABLE tags AS "Tags"
FROM "Meetings"
WHERE econtains(attendees, this.file.name)
SORT file.name DESC

On James Nematode’s person page, this works fine, and shows the name of the meeting (and any tags I included in the meeting’s frontmatter). However, the query can’t find Ralph Smith, presumably because his name is included in double brackets. I’m not sure how to get around this–am I not still searching for the filename string “Ralph Smith” in the attendees list {"[[Ralph Smith]]", "James Nematode"}?

I have used various versions of the code, e.g. WHERE contains(attendees, this.file.name) instead of econtains and WHERE econtains(attendees, this.person). The this.person just finds every meeting (I’m not sure why), whereas there doesn’t seem to be much if any difference between contains and econtains (expected, given the documentation of these functions). Is there a trick to using DQL to find a string in YAML in wikilink brackets?

I’ve also tried WHERE econtains(attendees, this.file.name) OR econtains(attendees, "[["+this.file.name) and WHERE econtains(attendees, this.file.name) OR econtains(attendees, "[["&this.file.name). Neither has any effect, but that may be due to my using incorrect syntax for string concatenation…

(As you might infer from the example, I’ll also be trying to figure out how to find aliases, e.g. either Ralph Smith or Ralphy Smith.)

Hello ato,
test this :

TABLE tags AS "Tags"
FROM "Meetings"
WHERE contains(attendees, "[[" + this.file.name + "]]") OR contains(attendees, this.file.name) OR contains(attendees, this.person) OR contains(attendees, this.aliases)
SORT file.name DESC

I hope it working well.

Bye

Thanks @glvercellone! Unfortunately, the same patterns I mentioned apply with your code as well: contains(attendees, "[[" + this.file.name + "]]") doesn’t find anything, and contains(attendees, this.person) finds all meetings, regardless of who the attendees are. So, the code you posted just shows a list of all of the meeting notes I have (since contains(attendees, this.person) is present as an OR option.)

Also, I realized that I messed up the aliases data structure in my original post, which I can’t seem to edit. It should be a list, viz.:

Ralph Smith
---
person: Ralph Smith
aliases: 
  - Ralphy Smith
title: Director of Sublimation
---

Hello ato, we try again , Test this code:

TABLE tags AS "Tags"
FROM "Meetings"
WHERE contains(attendees, this.file.name) 
   OR contains(attendees, this.person) 
   OR this.aliases.some(alias => contains(attendees, alias))
SORT file.name DESC

Ensure that your meeting notes are formatted so that the names of the attendees match exactly those specified in the person field or aliases. This is crucial for the correct matching in Dataview queries.

Bye.

You’ve got two issues in your code. First of all you need to get the links defined correctly within your properites, and secondly you need to query them correctly.

Links in properties

Put the following code in a note of its own and switch to reading or live preview:

---
alternatives:
- [[Ralph List]]
- Ralph Text
- "[[Ralph Link]]"
---

```dataview
TABLE WITHOUT ID
 alternative, typeof(alternative)
WHERE file = this.file
FLATTEN alternatives as alternative
```

You should get an output resembling:

Your original definition of a “link” is actually an array of arrays, or a list of lists, which in the table is shown as the double bullet, and the typeof array. If you look in the outlinks pane for this document, you’ll also see that only the “Ralph Link” is an actual link.

In other words, a link in the properties/frontmatter needs to be written as ""[[Your link]]"

Querying the result

If I understand your request correctly, you’ll want to list all the meetings from a given persons perspective, based upon the attendees property:

  • Direct link, aka "[[Ralph Smith]]"
  • Aliased links, aka "[[Ralph Smith|Ralphy Smith]]"
  • Full name, aka Ralph Smith
  • And aliased names, aka Ralphy Smith

So given the attendance list below, Ralph would have quadrupled himself :slight_smile: :

attendees:
- "[[Ralph Smith]]"
- "[[Ralph Smith|Ralphy Smith]]"
- Ralph Smith
- Ralphy Smith

So when these links are properly formatted we can compare it to the current file link, and use string matching in the other cases. So singling out the special case above, I did this query:

```dataview
TABLE WITHOUT ID attendee, typeof(attendee), status
WHERE file.name = "Quadrupled"
FLATTEN attendees as attendee
FLATTEN choice(typeof(attendee) = "link",
  this.file.link = attendee,
  this.person = attendee OR econtains(this.aliases, attendee)
) as status
```

Which gave me the output of:
image

This query split the attendees into each attendee, and do a check based on the type of attendee. If a link, check if it matches this persons link (I’m within the “Ralph Smith” note with this query), and if it’s a string it compares either to this.person (which also could have been this.file.name) or fully found within his aliases.

Generalising the query

This part I’ve not tested yet, as I’ve not built up multiple meetings, so hopefully it works.

```dataview
TABLE tags as "Tags"
FROM "Meetings"
FLATTEN any(map(attendees, (attendee) =>
  choice(typeof(attendee) = "link",
    this.file.link = attendee,
    this.person = attendee OR econtains(this.aliases, attendee)
  ))) as status
WHERE status
SORT file.name DESC
```

In addition to the matching from previous query, we here use that match statement to map each of the attendees to whether they’re present or not in the current meeting. The any( ... ) then checks if any of those statuses are true, indicating that this person attended that meeting.

@holroy Thank you so much for this detailed explanation and tutorial. I really appreciate it, and especially the techniques for seeing the data types–it was frustrating to me not knowing what I was dealing with. And your final code block did work!

I was able to generalize your code and explanation to implement a similar query with another field as well. Thanks again!

1 Like

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