Does a dataview query always select pages (i.e. notes)?

What I’m trying to do

I’m trying to get a better understanding of how dataview queries work. This may be a very trivial question, but it would be great to get clarification on that: am I understanding correctly, that a dataview queries generally operate at the level of pages/notes/files? By that I mean that the selection/filtering that is done with FROM and WHERE is always at the level of pages/notes/files so that if I want the query to return only specific elements from those notes, I need to specify those after LIST or TABLE?

The exception, of course, is TASKqueries, which operate directly at the level of tasks. So, my question does not concern these.

Side note: I would wish for an ITEMquery, which would target list-items directly, just like TASKS targets tasks. It seems to be the logical continuation of the similarities between list-items and tasks described (and implied) in the documentation here: Metadata on Tasks and Lists - Dataview. Or perhaps this already exists, somehow?

Things I have tried

I started off with this query

```dataview
LIST filter(file.lists.text, (t) => contains(t, "#ai-history"))
FROM #ai-history
WHERE any(file.lists, (i) => contains(string(i), "#ai-history"))
```

It lists all list-items tagged with ai-history. But I didn’t like the redundancies in the queries and tried to simplify it:

```dataview
LIST file.lists.text
WHERE contains(file.lists.tags, "ai-history")
```

but this doesn’t work because it lists all list-items from every note that contains a list-item with the tag.

(Strangely, the removal of FROM #ai-history also entails that an additional note is included. That additional note has a list-item with the ai-history tag, but the note itself doesn’t have that tag. This may be a bug.)

Anyway, here is the simplest version of the query I could come up with:

```dataview
LIST filter(file.lists.text, (t) => contains(t, "#ai-history"))
FROM #ai-history
```

What I don’t like about it, though, is that the actual query is done by the filter() function rather than the query itself, if that makes any sense. I would find it more satisfying if I could state the conditions using WHERE but that doesn’t seem to be possible because dataview queries select pages, not items. Is that correct?

I think the above is enough to explain my question, but here are some more thoughts, if you're interested.

Another imperfection with this query is that it doesn’t actually use actual tags when filtering, it just looks for text that looks like the tag. Fixing this is more an aesthetic challenge than anything else, but one way would be this

```dataview
LIST filter(file.lists.text, (t) => contains(t, "#ai-history"))
FROM #ai-history
WHERE contains(file.lists.tags, "ai-history")
```

But the added line is entirely redundant, so it makes no sense. So to avoid working with strings when I’m only interested in tags, I guess I would have to do

```dataview
LIST filter(file.lists, (f) => contains(f.tags, "ai-history")).text
FROM #ai-history
```

I then tried removing FROM #ai-history but then I get an empty line for every note in my vault because the filter I specified after LIST is only a display-filter, not a real query filter.

This kind of sums it up nicely: what bothers me is that I’m forced to use the display filter after LIST to formulate my query, but then I can’t go all the way and use only that filter.

1 Like

I specialize in misunderstanding everything, so this is probably not what you are looking for, but on the off chance …

## list
- woof:: small dog
- woof:: hot dog
- woof:: big dog 
- woof:: cool dog
- woof:: wolf

## query of list above

```dataview
LIST WITHOUT ID
item.text
WHERE file.name = this.file.name
WHERE woof
FLATTEN file.lists as item
SORT item.text ASC
```


EDIT:

```dataview
LIST WITHOUT ID
item.text
WHERE file.name = this.file.name
FLATTEN file.lists as item
WHERE contains(item.text, "big")
SORT item.text ASC
```

```dataview
LIST WITHOUT ID
item.text
WHERE file.name = this.file.name
FLATTEN file.lists as item
WHERE contains(item.text, "l")
SORT item.text ASC
```
1 Like

What you list are the typical row elements, but using FLATTEN and GROUP BY you can split and join any list construct. Notes, tasks, list items (from literal lists or whatever origin), there are loads of sources/constructs which can be used in this context.

2 Likes

Oh, this makes me even happier:

## paragraphs
woof:: small dog 

woof:: hot dog  

woof:: big dog   

woof:: cool dog   

woof:: wolf  

## q1

```dataview
LIST WITHOUT ID woof
FLATTEN woof
WHERE this.file.name = file.name
SORT woof ASC
```

## q2

```dataview
LIST WITHOUT ID
woof
WHERE file.name = this.file.name
FLATTEN woof
WHERE contains(woof, "i")
SORT item.text ASC
```

Source: How to recall several sentences from several notes in one place? - Help - Obsidian Forum

What an interesting specialization :slight_smile:

I specialize in figuring out what it is that people are misunderstanding (i.e. I‘m a teacher), but I‘m not so good at it… The interesting thing is that you learn a lot either way.

At first, I had difficulties seeing the connection bewteen your answer and my question, but I figured it must have something to do with the FLATTEN command, which I had thus far shied away from because I just couldn’t wrap my head around it. So I sat down and tried to understand it once more and I kinda succeeded sufficiently to be able to apply it to my example in the OP:

```dataview
LIST item.text
FROM #ai-history 
FLATTEN file.lists as item
WHERE contains(item.tags, "ai-history")
```

It took me a while to figure out that the FLATTEN command had to come before WHERE. I don’t understand the logic given that I can use ‘item’ in the LIST command before it is even defined, but anyhow, the above query works and is sp,ewhat more satisfying but I have not been able to get the output grouped by note/file (the examples in the OP where grouped in this way “naturally”). I think it is because the file name somehow is lost in the flattening or something.

The other issue is that, similar to the second example in the OP, I am forced to use FROM #ai-history because of the apparent bug mentioned earlier. But perhaps it improves performnce if the scope of files is limited with FROM, so it’s not a big deal.

Is it because you found a way of targeting plain paragraphs simply by adding a field to them?

1 Like

Yes, absolutely.

I don’t have a firm grasp on any part of Dataview: I have learned by trial and error, and in many cases queries suddenly work as I need them to without me fully understanding the how or why serendipity has suddenly struck.

I have read the Dataview help pages countless times and have come to the conclusion that the authors (of the plugin and online resources) assume that users will either already have some experience of coding logic or simply (like me) muddle through.

I know this is poor etiquette, but I am going to ‘at’ @holroy (apologies, holroy) in the hope that he—being a coder par excellence—will be able to offer something more lucid and rational for you.

1 Like