Query that lists all notes that have one or more of the same field values

What I’m trying to do

I am trying to make a query that lists all notes that have one or more of the same field values as in the currently open file and have the tag #setting.
However, the result shows all the notes in the vault that have the tag #setting.

If only one field value is set in the currently open file, instead of several field values, everything works as it should.

I am afraid that there is a syntax error in my query, so that the field value for “proj” is ignored as soon as more than one field value is set in the currently open file:

LIST
FROM #setting 
WHERE contains(proj, this.proj) AND file.path != this.file.path
SORT file.name ASC

Things I have tried

Unfortunately, I am not very experienced in writing code, so I just can’t find a solution to make this work reasonably

Could you give some example of field defintions (and values) which work, and which don’t work?

If you’re asking a question on how to verify that a list of values is equal to another list of values, then maybe the post below could help you move forward, as you then need to do some combinations of any/all/… and map and contains.

Sure, the individual notes have a field definition, “proj::”.
In the currently open note it is (proj:: [[Rom]], [[Portal]]). So this note refers to the values “Rom” and “Portal”.
I would now like to use Dataview to display all notes that also have “Rom” OR “Portal” as a field value of “proj”.

If more than one field value is assigned to the variable “proj” in the current note, I now get all notes of the vault displayed that have the tag #setting. The query “contains(proj, this.proj)” seems to be ignored in this case:
image

However, if I now have only one field value for “proj” in the currently opened note, everything works as it should. Only the correct note “01GA_Gate” is displayed:
image

Does this work?

```dataview
LIST FROM #setting 
WHERE contains(proj, [[Rom]])
OR contains(proj, [[Portal]])
AND file.path != this.file.path
SORT file.name ASC
```

Thank you eightning, this works perfectly.
But in my case the values should correspond to the condition “Field value x = one of the field values x in the active file”. But in the multiple values seems to be the cause of my problem

1 Like

I assume that if the stored values are two (or more) items that the condition looks for all the items rather than one OR other of the items. I don’t know how to change that, but I expect holroy will have a solution for you.

2 Likes

Thanks for the confidence… :smiley: I’ve already alluded to the solution, I think, in a previous post, and I hope the following might do the trick:

```dataview
LIST
FROM #setting
FLATTEN 
  choice(typeof(this.proj) = "string",
    list(this.proj), this.proj) as projList
WHERE file.path != this.file.path
WHERE any(map(projList, (p) => contains(proj, p)))
SORT file.name ASC
```

There are two key variations in this script compared to the original script:

  • Ensure this.proj is always a list, e.g. projList
  • Check proj against all values in projList

Ensure this.proj is always a list

Since this.proj can be a single-value or a multi-value field, it’ll cause issues if we don’t do some trickery. I found that it’s best to just ensure it’s always a list, and handle the multi-value case as the default case. This part of the query handles this:

FLATTEN 
  choice(typeof(this.proj) = "string",
    list(this.proj), this.proj) as projList

This checks to see if this.proj is a string, aka a single value, and if so it does the list(this.proj) which makes a list with just that one value. If it’s already a list, then just keep using this. Store the result of this into projList.

Do note that you to trigger an array creation in an inline field you’ll need to use quotes. Try the following in a note to see the differences:

[projA:: Portal]  
[projB:: Portal, Rom]
[projC:: "Portal", "Rom"] 
[projD:: Portal]
[projD:: Rom]

 typeof projA --> `= typeof(this.projA) `
 typeof projB --> `= typeof(this.projB) `
 typeof projC --> `= typeof(this.projC) `
 typeof projD --> `= typeof(this.projD) `

This should report “string”, “string”, “array” and “array”
See how only the latter one is reported as an array (or list) of multiple values. projB is just one value of “Portal, Rom”, not the two separate values. So either you’ll need to use quotes around multiple values (aka projC), or you need to add them in different defintions (aka projD).

Check proj against all values in projList

When we’ve ensured that projList is the list of the various projects we want to check against, we need to do the double loop. If I understood you correctly you wanted to list all notes matching any of the projects, so that lead to this query part:

WHERE any(map(projList, (p) => contains(proj, p)))

Lets try to explain it (again):

  • any( ... ) – Include the file if any of the arguments is true. Other variations could be all() or none()
  • map(projList, (p) => ... ) – Loop through all of the elements of projList, and for each of them use that element as m in the expression which follows. Keep track of the result of all these expression, and pass it onto the method above
  • contains(proj, p) – Use the “familiar” expression to check for the single value. That is check that proj contains the single value of p. If found return true, and if not found return false.

Hopefully, that explains the added logic, and gives you the result you wanted. Query is untested, as I don’t have files setup like you have sketched for us. One caveat could be if proj in the various notes have multiple values, but I think it should work in that case too. And as stated above, you do need to make sure that this.proj is an actual list, aka have quotes around the various values, for the query to work.

2 Likes

oh thank you holroy!!!
With your brilliant thoughts we enter the fourth dimension :wink: :wink: .
I would not have thought that Dataview would not offer a simple solution in this case.
Unfortunately, the problem is that I can no longer use the field values as a link. Did I understand you correctly that the values in this case generally have to be put in inverted commas?

What do you mean? I’m not sure I follow you here. If the field values (as strings) are containing a link, they’ll behave as a link when processed/displayed by Dataview.

You might need to change parts of the queries involved if you’re using stuff like [proj:: "[[Portal]]" ], but it should be doable (and live-preview could be a little confused, but that’s another matter).

In some of the example I’m using quotes, ", and those should be straight quotes. Not any of the smart “quotes”, as shown in this sentence. When doing an inline query, like `= typeof(this.projC) `, you do need to use the backtick quote, and not the straight single quote, ' or the acute quote, ´.

In short using the right quote characters can be confusing, but in general whenever we’re talking about coding/queries, it’s usually the straight variant of either the single or double quotes which are to be used.

Often in the forum posts here however, you could see the “smart” variants as the forum tries to make it look more elegant and fancy. If not properly escaped, this can produce code which will not work when copied into Obsidian.

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