Dataview JS, dv.func.contains returns no results (reading frontmatter with links)

Things I have tried

I am trying to adapt this query:

```dataview
table selection from #grow-bag and -"templates"
where contains(site,[[GS-43HOLM-BACKYARD-SHED]])
```

Which returns two results:

Into an inline count of results, using dataviewjs.

I have tried:

`$= dv.pages('-"templates" and #grow-bag').where((p) => dv.func.contains(p.site, "GS-43HOLM-BACKYARD-SHED")).length`

But this returns 0.

I feel like I am making a syntax error with where((p) => dv.func.contains(p.site, "GS-43HOLM-BACKYARD-SHED")) but I can’t work out what it might be.

I have tried wrapping the code in a full dataviewjs block element, like this:

```dataviewjs
let num = dv.pages('-"templates" and #grow-bag').where((p) => dv.func.contains(p.site, "GS-43HOLM-BACKYARD-SHED")).length

dv.paragraph(num)
```

but that returns 0 as well.

YAML frontmatter contents in GB-50-78L-03:

```
---
created: [[2022-09-01]]
tags: grow-bag
site: "[[GS-43HOLM-BACKYARD-SHED]]"
season: 2023
dimensions:
  height: 40
  diameter: 50
pockets:
  amount:
  diameter:
tray: [square]
potting_mix: [[grow bag soil mix|epic grow bag mix]]
selection: ["[[Navaho BigandEarly]]"]
manufacturer: "[[Elixir Gardens]]"
purchased: "[[Amazon]]"
---
```

What I’m trying to do

Dynamically count the number of files whose frontmatter contains site: “[[GS-43HOLM-BACKYARD-SHED]]”, excluding files from the templates folder.

Continuing using dv.pages() approach

Presuming site is a field in your pages, which contains a link. Links are icky.

For starters you should try out and see what the p.site actually holds, by doing something like:

```
let num = dv.pages('-"templates" and #grow-bag')
  .where((p) => {
    console.log(p.site)
    return dv.func.contains(p.site, "GS-43HOLM-BACKYARD-SHED"
  })).length

dv.paragraph(num)
```

It might help you locate the issue. And I reckon you need to look into the links variables to actually get a hold of the inner workings of the link.

You could also try to simply use dv.func.contains(p.site, "[[GS-42....]]"). Not tested that approach, but it could work? Or try using `dv.page("GS-43HOLM … ")?

But my favorite way of testing links with this approach is doing something like p.site?.path = dv.page("GS43...").path. It does come with its own caveats related to site not being a link, or the test page not existing, but it does work in most cases for me.

Using the DQL within the query

Another option I tend to use is something like the following:

```dataviewjs
const result = await dv.query(`
  table selection from #grow-bag and -"templates" 
  where contains(site,[[GS-43HOLM-BACKYARD-SHED]])
`)

if ( result.successful ) {
   dv.span(result.value.values.length)
} else
  dv.paragraph("~~~~\n" + result.error + "\n~~~~")   
```

Or if you’re feeling braver:

```dataviewjs
dv.span( ( await dv.tryQuery(`
  table selection from #grow-bag and -"templates" 
  where contains(site,[[GS-43HOLM-BACKYARD-SHED]])
`).values.length )
```

(This could also be made into a one liner, which I leave as an exercise to the reader. :smiley: )

The advantage of this method, is that you can copy the query into the dataviewjs query, and not worry about how the syntax changes if going the alternate route.

Bonus tip: How to present code properly in a forum post

If you want to showcase either markdown, or code blocks, or dataview queries properly in a forum post, be sure to add one line before and one life after what you want to present with four backticks, ````. This will ensure that any other backticks (like for code blocks) is properly shown.

2 Likes

Thanks Holroy, I have added in the YAML frontmatter from GB-50-78L-03. This is one of the notes that’s being picked up correctly by the regular dataview contains query.

I made a mistake posting my reply a little early, so I’ve now adapted it a little more to be a little more inline with what I was thinking to write (before posting).

Thank you so much @holroy, your await dv.tryQuery approach turned out to be the key. I was able to extend your final query into the following code:

```dataviewjs 
dv.span("Total sites available: ")
dv.span((dv.current().file.frontmatter.fits.spaces_available))
dv.span(", now in use: ")
dv.span(( await dv.tryQuery(` 
	table selection from #grow-bag and -"templates"
	where contains(site,[[GS-43HOLM-BACKYARD-SHED]]) `)).values.length ) 
```

Rendering as:

This will give me a dynamic view of my inventory as I start allocating pots in the garden this summer.

I really appreciate the time you made to teach me today.

Happy to be of assistance. You could also try to gather up all those dv.span()'s into one dv.paragraph(). Untested code follows…

```dataviewjs 
dv.paragraph("Total sites available: " + 
  dv.current().file.frontmatter.fits.spaces_available +
  ", now in use: " +
  (await dv.tryQuery(` 
	table selection from #grow-bag and -"templates"
	where contains(site,[[GS-43HOLM-BACKYARD-SHED]]) 
   `)).values.length
) 
```

If it works (hopefully it does), this should render slightly better instead of using multiple span elements.

In case this helps others, I have now discovered that the following also works:

`$= dv.pages('"grow_bags"').where((p) => p.site.toString() == dv.current().file.link).length`

It seems that it is possible to skip dv.func.contains altogether by casting the YAML to a string and then comparing it to file.link.

Note: GS-43HOLM-BACKYARD-SHED is the name of the note in which this code runs

Of course this solution will only work if you are comparing a link to a link. If you need to compare a link to a string, then @holroy’s approach is far superior.

1 Like

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