Dataview multiple variables in the same note

My issue is somewhat similar to the following: Using multiple tags on a single note with Dataview

What I’m trying to do

I have come across this issue multiple times in the past, I would like to be able to query a specific line of inline variables within a note and have them query separately in dataview, even if the same inline variables are used somewhere else.

Example:

Below is my daily note format, I use daily notes as the brain dump with a bunch of inline fields and then want to be able filter out specific information later using dataview. This works incredibly well using TASKS (because they’re little contained packages), but not well using anything else by the looks of it. I really want to be able to query bullet points as well as I can for tasks.

The example that i came across is that I want to run an annual leave log for a set of people, as my daily notes is my centre, I input all the leave so far in the daily note under different bullets.
When I try and query them in dataview, it can’t separate anything within the same note.

---
starttime: 08:55
lunchtime: 30
finishtime: 
othertime: 
tags:
  - DailyNote
---
#### (date:: 2024-02-28)
---
# Log 
- [ ] Task example 1 || [duedate:: ] || [project:: ] || [topic:: ] || [priority:: ] || (person:: Person1) || (type:: work) || (date:: ) || (state:: ) || 
- [person:: "Person1", "Person2", "Person3", "Person4"] || [leavedays:: 3] || [leavestart:: 2024-12-27] || [leaveend:: 2024-12-31] 
- [person:: Person2] || [leavedays:: 5] || [leavestart:: 2024-02-12] || [leaveend:: 2024-02-16]
- [person:: Person2] || [leavedays:: 13] || [leavestart:: 2024-05-29] || [leaveend:: 2024-06-14]

The following query might get you a little closer to your intentions:

```dataview
TABLE item.person as "Person(s)", item.leavedays as "AL days", item.leavestart as Start, item.leaveend as End
WHERE leavedays
FLATTEN file.lists as item
WHERE item.leavedays
```

This would scan all files in your vault, and pull out those having leavedays defined somewhere, and then split the lists of that file, and further select only list item having leavedays defined, and finally produce a listing of this leave periods.

Hope this helps, and that the untested query actually works in your context. :smiley:

Update: Corrected some typos with the quotes

1 Like

Unfortunately your dataview code is throwing up an error:

"Dataview: Error:
– PARSING FAILED --------------------------------------------------

1 | TABLE item.person as “Person(s)”, item.leavedays as “AL days”, item.leavestart" as Start, item.leaveend" as End
| ^
2 | WHERE item.leavedays
3 | FLATTEN file.lists as item

Expected one of the following:

‘(’, ‘*’ or ‘/’ or ‘%’, ‘+’ or ‘-’, ‘,’, ‘.’, ‘>=’ or ‘<=’ or ‘!=’ or ‘=’ or ‘>’ or ‘<’, ‘[’, ‘and’ or ‘or’, /FROM/i, /[0-9\p{Letter}_-]/u, EOF, FLATTEN [AS ], GROUP BY [AS ], LIMIT , SORT field [ASC/DESC], WHERE , text, whitespace"

Try now, after I’ve corrected spør typos on the first line with the quotes.

1 Like

That did it! I also used SORT item.leavestart ASC

I have never seen item.variable or file.lists used before, is there a place where i can find all these extended dataview callouts?

Can you explain the 2x WHERE callouts to me? Why did you need WHERE leavedays and WHERE item.leavedays?

If I had a text before each of these variables that i also wanted to pull into the table, how would I go about doing that?

i.e.

- text before inline variables 1 [person:: "Person1", "Person2", "Person3", "Person4"] || [leavedays:: 3] || [leavestart:: 2024-12-27] || [leaveend:: 2024-12-31] 
- text before inline variables 2 [person:: Person2] || [leavedays:: 5] || [leavestart:: 2024-02-12] || [leaveend:: 2024-02-16]
- text before inline variables 3 [person:: Person2] || [leavedays:: 13] || [leavestart:: 2024-05-29] || [leaveend:: 2024-06-14]

For file.lists & co, see Metadata on Pages - Dataview. Regarding item that’s not available until you do a FLATTEN file.lists as item, and you can name it whatever you like. I’ve just happened to land on mostly using item since it makes sense to me to talk about one item in the file.lists. I also use task when flattening the file.tasks. It’s just a naming convention I’ve chosen.

Let us imagine that every file has at least 10 items in various lists, and you’ve got a 1000 notes in your vault. If we skip the first WHERE clause, then we would expand those 1000 notes into 10 000 rows of items for further processing. When we do the first WHERE leavedays we only focus on notes which actually declares that field somewhere within itself. This could easily narrow down the number of files, to say 50 files just for the sake of this example.

Then we split those 50 notes (not a 1000 notes anymore) into 500 rows of items, but we still have random items which are just ordinary list items in other types of list, so then we use the WHERE item.leavedays to only include the item actually having the wanted information.

So all in all, it’s just a way of reducing the load in two steps, to hopefully make the query run a little bit faster and be easier on the resources available.

There is a lot of information available in a list item, i.e. in item in our case, and the pure raw text of the list item is in item.text. You could just add that into the column, or even just try item to see all of the information available to each row in this query.

I often tend to clean up the text by removing extra information, so in your case you could try adding another FLATTEN line under the other one, and do something like:

```dataview
TABLE WITHOUT ID text, item.person as "Person(s)", item.leavedays as "AL days", item.leavestart as Start, item.leaveend as End
WHERE leavedays
FLATTEN file.lists as item
FLATTEN regexreplace(item.text, "\[[^\]]+::[^\]]+\](?:\s*\|\|\s*)?", "") as text
WHERE item.leavedays
SORT item.leavestart ASC 
```

Here we remove any text from item.text like [ ... :: ... ] optionally followed by ||, before storing into text, which is then used in the display.

1 Like

Makes so much sense, I really appreciate the in-depth responses.

Dare I ask about the regexreplace? I understand the basic principle of what it does, but what have you specified in your term? regexreplace(item.text, "\[[^\]]+::[^\]]+\](?:\s*\|\|\s*)?", "")

Thanks again.

I’ll try to explain it, but one very useful resource when working with regex is to use regex101: build, test, and debug regex . Make sure it’s set to “ECMA Script/javascript” on the lefthand side (or through the settings). This tool will in addition to help you build and test your regex, also give sort of an explanation to it. The link above is with it preloaded to the regex in question.

Here goes the explanation:

  • \[ – This matches the literal left square bracket, [. It needs to be escaped with a backslash, \, since the square bracket is also a start of a character class
  • [^ ... ]+ – This is a negative character class, where it matches any character but those listed. In our case, \], so any character not being a right bracket. This particular character is used since that is a required character when making a visible inline field, and ensures we don’t accidentally match multiple inline fields on the same line. The plus sign, + after the group is to ensure there is at least one non-matching character
  • :: – Then we match the literal sequence of two colons, ::, which is the separator of the key and value in an inline field
  • [^\]]+ – Same as above, but this time we’re actually looking for the end of the field
  • \] – And the end of the field is the literal right square bracket, ]. Also this escaped due to the character class meaning
  • (?: ... )? – The inline field is followed by 0 or 1 non-capturing groups of something, where ( ... ) is a capturing group, and the (?: ... ) is the non-capturing variant, and the ? marks the 0 or 1 variant. This means we check for an inline fields optionally followed by this group
    • \s* – And the group starts with 0 or more, *, space characters, \s
    • \|\| – Two literal pipe characters, |, which also are escaped (since they also could server as alternate options)
    • \s* – And some more optionally space characters

So all in all, it matches one inline field defined by [ ... :: ... ] where the text within is anything but the right square bracket, optionally followed by || optionally surrounded by space characters.

1 Like

Amazing!! I’ll give that tool a go in other examples too. Thanks again @holroy, you’re help is massively appreciated.

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