Dataviewjs to show the lists grouped by values of the key

What I’m trying to do

Recently, to improve readability, each item in a list has an inline property that describes what it contains

  • (key:: value) - contents

And I used a dataviewjs to sort by value for that key and laid it out in a spreadsheet.
I expected like this

A

  • A :
  • A :
B

  • B :
  • B :

Things I have tried

const notetable = await dv.query (`
TABLE WITHOUT ID rows.L.concepts as "Concepts", rows.L.text as "contents"
WHERE file.path = this.file.path
FLATTEN file.lists as L
GROUP BY L.concepts
SORT L.concepts ASC
`)

console.log(notetable)

if (!notetable.successful) {
  dv.paragraph(`~~~~\n{ notetable.error }\n~~~~\n`)
  return
}

let typeDict = {}
for (let note of notetable.value.values) {
  if ( !typeDict.hasOwnProperty(note[0]) ) 
    typeDict[note[0]] = []

  typeDict[note[0]].push([...note.slice(1)])
}

for (let key of Object.keys(typeDict)) {
  dv.header(5, key)
  dv.table([...notetable.value.headers.slice(1)],
    typeDict[key])
}

it’s my dataviewjs code. and conceptual lists are below

  • (concepts:: A) : drawing picture
  • (concepts:: C) : picturing photo
  • (concepts:: B) : copying shot
  • (concepts:: A) : drawing picture

and actual result is like below

A,A

  • (concepts:: A) : drawing picture
  • (concepts:: A) : drawing picture
B

  • (concepts:: B) : copying shot
C

  • (concepts:: C) : picturing photo

As you can see, header of each group increases as the number of list’s increases.
How can I fix this

Try this variant of your query, and keep the rest of the script:

const notetable = await dv.query (`
TABLE  rows.L.text as "contents"
WHERE file.path = this.file.path
FLATTEN file.lists as L
GROUP BY L.concepts as Concepts
SORT Concepts ASC
`)

I think that’ll fix it. I often test run queries like these outside of the script just to verify that it’ll do what I exoect it to do, and if you had done that you would have seen the same behavior there.

Using the rows.L.concepts would give you a repeated value corresponding to the number of rows. You could have used key instead of that expression since in a GROUP BY there is two things happening, the rows get populated with lists of corresponding fields like like your L.text, and the key gets the unique value of the GROUP BY expression.

I’m not sure if key is preserved when we rename the grouping like I just did, but I think it does.

I commend you on building the headers based on the groups, but if you just want to display one list from each group you might consider something like the following too:

```dataview
LIST rows.puretext
WHERE concepts
FLATTEN file.lists as item
WHERE item.concepts
FLATTEN regexreplace(item.text,  "^\([^\)]+\)\s*:\s", "") as puretext
GROUP BY "<span style='font-size: 1.2em; font-style: bold;'>" + item.concepts + "</span>"
SORT key DESC
```

Which with the test data given produces this list:
image

This query showcases two elements, and that is that using GROUP BY in a list query shifts the first level to be the key of the grouping, and then you can use a rows.* expression to present the grouped elements. I tossed in some random styling on the key just to show it’s possible.

The second element this query showcases is the removal of the inline fields before presentation into the puretext fields. Similar stuff can be done for square brackets inline fields, and/or tags and so on.

When working with this reply, I found that it’s indeed preserved.

Thanks for your help, I didn’t know that

and, about your second reply, I also didn’t know I can use ‘double’ WHERE+FLATTEN in my query. it works perfectly. thanks.

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