How to use the dataview plugin to search the certain keywords

Things I have tried

Hello,
I want to use the dataview plugin to search the keywords. Please see the following example.

1

I set the 「Q::」

2

I tried to type the code as below,

table Q
from "共用"
where contains(Q,"A_a109")
sort file.ctime desc

3
I only want to show 「 TEST1(A_109)」because it contains the keyword 「A_a109」. But the result is not correct.

Can you help me with this question? What code should I write? Thanks you very much.

Perhaps this way?

table Q
from "共用"
flatten Q
where contains(Q,"A_a109")
sort file.ctime desc
3 Likes

It works. Thank you so much for your help.

Hi JLDiaz,

There is another question, when I use tag.
1

2

table Q, tag
from "TE"
where contains(tag,"#one") 
sort file.ctime desc


I only want to show 「 456」because it contains the tag 「#one」. But the result is not correct.

Could you please help me with this question? Thanks you very much.

I don’t think you can do what you are trying to do, unless you change your approach.

I assume that the part which contains Q:: 456 etc, and the other with Q:: 789 are part of the same document. As far as I know, that only means that your document has several fields Q (and also several A and several tag), but you cannot see them as “grouped”. I mean, you apparently assume that the first tag: “pertains” to the first Q:, and thus you want to show only that first “group”.

However, what really happens, is that the document has a list of values for Q and a list of values for tag, and those lists are not related, except perhaps for their indexes.

I think that the proper approach would be to define your data as a list in the yaml preamble, for example like this:

---
meta:
- Q: 456
  A: ()
  tag: "#one"
- Q: 789
  A: ()
  tag: "#two"
---

(note the need of enclosing the tags between quotes).

This way you have indeed two groups of metadata, each one being a dictionary with Q, A and tag fields. So you can now create the following dataview:

table meta.Q as Q, meta.tag as tag
from "TE" 
FLATTEN meta
where contains(meta.tag, "one")

Which produces:

image

Also, if you insist in having the data as part of the document in a “unstructured” form like this:

 Q:: 456
 A:: ()
 tag:: #one

 Q:: 789
 A:: ()
 tag:: #two

 Q:: 128
 tag:: #one

then you can use the following dataviewjs:

let transpose = m => m[0].map((x,i) => m.map(x => x[i]));
let p = dv.pages('"TE"')
let result = transpose([p.Q, p.tag])
result = result.filter(x=>x[1] && x[1].contains("one"))

dv.table(["Q", "tag"], result)

which produces:

image

but I find this approach very brittle because it relies on the order in which Q and tag appear. If, for example, the second group with "Q:: 789" was missing a tag, then the document will have three Q and only two tags, so that the correspondence Q[0] → tag[0], Q[1] → tag[1], Q[2]-> tag[2] will be broken.

Thank you so much.

It is difficult. I tried to use the dataviewjs you provided. It can work.

But I found 3 questions when using

  1. The filename wasn’t appear in the table.
    How to appear that column?
  2. In the different document, if there are the same 「Q」, it will show all. So I think it might add the filename column so I can see what is this 「Q」from.
  3. When I tried to sort the result, for example, sort tag desc, it can’t work.
    How can I sort tag by desc?

Could you please give me some idea? Thank you so much.

So you have several Q:: and tags:: in several files? Can each file contain this data repeated several times?

I prepared two files, one called “Test1” and the other called “Test2” containing the following:

# This is test1

Q:: 1111
A:: ()
tag:: #one

Q:: 1112
A:: ()
tag:: #two

Q:: 1113
tag:: #one
# This is test2

Q:: 2221
tag:: #three

Q:: 2222
tag:: #one

Q:: 2223
tag:: #two

Q:: 2224
tag:: #one

And prepared in a third file the following dataviewjs:

tag_to_filter:: one

```dataviewjs
// utility function
let transpose = m => m[0].map((x,i) => m.map(x => x[i]));

// Variable for storing results to show
let all_results = []

// Get all notes from all files (change "" to a folder if required)
// and group the data by file, keeping only those which have a Q property
let files = dv.pages('""').groupBy(p=>p.file).filter(g => g.rows.Q.length);

// For each file, process the found data
for (let group of files) {
    let p = group.rows;
	
	// Get all Qs and all tags, paired by index,
	// and keep only those with tag "one"
	let Qs = p.Q
	let tags = p.tag
	// Temporally assign empty string to filename
	let filenames = new Array(Qs.length).fill("");
	
	// Build a sub-table for this file
	let result = transpose([filenames, Qs, tags])
	// Keep only the rows for which the tag contains "one"
	result = result.filter(x=>x[2] && x[2].contains(dv.current().tag_to_filter))
	
	// Now assign the filename to the first row of the subtable
	result[0][0] = group.key.link;

	// And store the subtable in the global variable
	all_results.push(...result)
}
// Show all the sutables in a sigle table
dv.table(["File", "Q", "tag"], all_results)
```

When run, it produces the following table:

image

is this what you wanted? The table shows the file names (to avoid repetition, only the first row for each file shows the name and link, rows below those refer to the same file), the values of Q and the tag being filtered. You can change which tag is filtered by editing the field tag_to_filter::.

Still, I think the approach is brittle, and I’m not very proud of the code… Comments are welcome.

Thanks for your help.

The coding is so difficult for me.

But I will try it. It helps me a lot. :slightly_smiling_face:

image

I’m wondering if there is any way to hide the “tag” column because I know it already from filtering by ‘tag_to-filter:: one’.

My solution.

After

 result = result.filter(x=>x[2] && x[2].contains(dv.current().tag_to_filter))
var idx = 2;
for(var i = 0 ; i < result.length ; i++) {
    result[i].splice(idx,1);
}

Inserting the above codes, I succeeded in hiding ‘tag’.

Hi, JL~Could you have a look at this case:

I try to query the data containing a keyword from csv, but the query result is incomplete (often 0) ……

PS. The reference field has multiple values "[[123]], [[456]], [[789]]"

TABLE WITHOUT ID content, reference
FROM csv("Database/qust.csv")
flatten reference
WHERE contains(reference, "123")

I think flatten doesn’t do anything with multiple values in csv file (or depends in the way how the commas are added to field… for now I didn’t find a valid way).
And attention because your values are links, not strings (contains has different behaviors for one or another).
Try this query:

TABLE WITHOUT ID content, reference
FROM csv("Database/qust.csv")
WHERE contains(string(reference), "123")

(string(reference) transform your links in strings - only for query purposes)

Thank you! But the result doesn’t seem to change ……

hmm, strange. works with me.
image

image

image

1 Like

Oh, it works now. It seems that there is a problem with my CSV editor, resulting in data reading errors.
Thank you very much. This problem has bothered me for a long time :rofl:

When ‘Test1’ and ‘Test2’ are in the same folder, the following error happens.

Evaluation Error: RangeError: Maximum call stack size exceeded
at Function.keys ()

Could anyone help me solve this problem?

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