Aggregating personal details from meeting notes into Person pages

Problem:

When I meet with the same person multiple times, I feel bad when I don’t remember “the little things” about them. I want to have an easy way to extract personal details (e.g. college attended, favorite foods, kids’ names, partner name, etc…) from meeting notes into a Person page for individuals with whom I speak on a regular basis. This will also help me to thoughtful things for them over time that are personal to them.

Solution:

I include the snippet below in the Personal Notes section (header 2) of my Person template:

const personString = dv.current().file.name.split(" ").join("");

dv.list(dv.pages("").where(p => p[personString])[personString])

All of my Person notes in my People folder are titled with just the person’s name. So, the above snippet allows me to type the person’s name (caps sensitive) as inline metadata in any note, extract those details, and aggregate that text in the hub note for that Person. The line gets printed in the Person note as the actual text rather than just the link to the file.

E.g. if I write the below in any note, what will get printed in the Zack Ellis page will be “kids are Pinky and The Brain”

ZackEllis:: kids are Pinky and The Brain

The next thing I want to do is to figure out how to print both the file link and the plain text…e.g.

[[2022-11-23 Zack Ellis]]: kids are Pinky and The Brain

This is how Dataview works if I do something like:

list book
from ""
where book

to aggregate recommended books from different people:

7 Likes

This is cool. I do something similar but exactly the opposite way… that is, I keep ‘people notes’ and show meetings that they were in.

I played with the idea of pulling ‘people note’ facts into a ‘meeting note’. Some assumptions I made were:

  1. The ‘people note’ has the tag ‘#person
  2. The meeting lists who is attending using an outgoing link, e.g. …
# Attendees
- [[John Smith]]
- [[Jane Doe]]

Below is what I came up with…

DataView JS Code…

let facts = ["children", "hobbies"]
displayAttendeeFacts(facts)

function displayAttendeeFacts(facts) {
	let people = getLinkedPeople()   

	let tableColumns = ["person"].concat(facts)
	let tableDataFunction = (page) => {
		let personColumn = [dv.fileLink(page.file.name)]
		let factColumns = facts.map(fact => page[fact])
		return personColumn.concat(factColumns)
	}
	
	if (people.length > 0) {
		dv.table(tableColumns, people.map(tableDataFunction).sort(page => page.file))
	} else {
		dv.paragraph("No people.")
	}
}

function getLinkedPeople() { 
	// Get filenames from outgoing links
	let outlinks = dv.current().file.outlinks || []
	let attendees = outlinks.map((link) => link.path.match(/.*\/(.*)\.md/)[1])

	// Retrieve 'people notes' with the same names as outgoing links
	let linkedPeople = []; 
	if (attendees.length > 0) {
		linkedPeople = dv.pages('#person')
			.filter(page => {
				let fileName = page.file.name
				let isNotATemplate = !fileName.contains("Template")
				let isAnAttendee = attendees.includes(fileName)
				return isNotATemplate && isAnAttendee
			})
	}

	return linkedPeople 
}
2 Likes

Love it. Very clever!

The question for a “non-coding” dummy - is how to achieve this type of outcome through existing tools or plugins, any ideas?

Dear Fyrefyta,

That’s a reasonable question. Not everyone is comfortable writing code. To my knowledge there isn’t a plugin that does what this query does.

If you want help getting this query working on your system, message me directly and I’ll help you out.

As an aside, it’s a lot of code to put into each “person file”. I’d recommend re-using the code by putting it into a “view”. Described here… Obsidian: Dataview Reuse. This article shows visually how to… | by Gareth Stretton | Oct, 2022 | Medium

Best of luck!

1 Like

Thanks for that. As I work on better articulating my use case and need, I may reach out, I appreciate the offer.

1 Like

Topic

Summary
  • How to pull the ‘person note’ metadata into a ‘meeting note’ via Dataview DQL query?

Test

Summary
  • dataview: v0.5.55

Input

Summary

the current note

  • Location: “100_Project/02_dataview/Q23_meeting/Q23_test_data”

folder: Meeting

  • filename : 20221217_meeting
```md
## Coffee Meeting

### Date
- 2022-12-17T16:00

### Attendees
- [[John Smith]]
- [[Jane Doe]]

### Host
-  [[Tom Felton]]


### Q23_DQL10 (OR Q23_DQL20)



```

dictionary files

  • Location: “100_Project/02_dataview/Q23_meeting/Q23_test_data”

folder: Persons

  • filename : Jane Doe
```yaml
---
tags: [ person ]
children: [ "Nicholas" ]
---

hobbies:: swimming

```

  • filename : John Smith
```yaml
---
tags: [ person ]
children: [ "Emily" ]
---

hobbies:: walking

```

  • filename : Tom Felton
```yaml
---
tags: [ person ]
children: [ "Eliza" ]
---

hobbies:: cycling

```

DQL10_pull_person_note_metadata_into_meeting_note_by_using_file.outlinks

Summary

Main DQL

Code Name Data type Group By Purposes Remark
DQL10
_pull_person_note_metadata
_into_meeting_note
_by_using_file.outlinks
(Meeting notes)
this.file.outlinks:
a list of links

(Person notes)
tags:
a list of strings
no 1.To break up a list this.file.outlinks into each individual element P
1.1 this.file.outlinks: a list of links
1.2 P: a link

2.To filter by P.file.name
3.To filter by P.tags
4.To display the result as a table

Code DQL10_pull_person_note_metadata_into_meeting_note_by_using_file.outlinks

Summary_code
title: DQL10_pull_person_note_metadata_into_meeting_note_by_using_file.outlinks =>1.To break up a list `this.file.outlinks` into each individual element `P` 1.1 `this.file.outlinks`: a list of links 1.2 `P`: a link 2.To filter by `P.file.name` 3.To filter by `P.tags` 4.To display the result as a table
collapse: close
icon: 
color: 
```dataview
TABLE WITHOUT ID
      P AS "person",
      P.children AS "children",
      P.hobbies AS "hobbies"

FROM "100_Project/02_dataview/Q23_meeting/Q23_test_data/Meeting/20221217_meeting.md"

FLATTEN this.file.outlinks AS P

WHERE !contains(P.file.name, "Template")
WHERE contains(P.tags, "person")
```

Screenshots(DQL10): using file.outlinks


DQL20_pull_person_note_metadata_into_meeting_note_by_using_L.outlinks

Summary

Main DQL

Code Name Data type Group By Purposes Remark
DQL20
_pull_person_note_metadata
_into_meeting_note
_by_using_L.outlinks
(Meeting notes)
L.outlinks:
a list of links

(Person notes)
tags:
a list of strings
no 1.To break up a list this.file.lists into each individual element L
1.1 this.file.lists: a list of links
1.2 L: a link

2.To define a field variable F_subpath
3.To define a field variable F_type
4.To filter by F_type
5.To filter by F_subpath
6.To FLATTEN L.outlinks AS P
7.To filter by P.file.name
8.To filter by P.tags
9.To display the result as a table

Code DQL20_pull_person_note_metadata_into_meeting_note_by_using_L.outlinks

Summary_code
title: DQL20_pull_person_note_metadata_into_meeting_note_by_using_L.outlinks =>1.To break up a list `this.file.lists` into each individual element `L` 1.1 `this.file.lists`: a list of links 1.2 `L`: a link 2.To define a field variable `F_subpath` 3.To define a field variable `F_type` 4.To filter by `F_type` 5.To filter by `F_subpath` 6.To FLATTEN L.outlinks AS P 7.To filter by `P.file.name`  8.To filter by `P.tags` 9.To display the result as a table
collapse: close
icon: 
color: 
```dataview
TABLE WITHOUT ID
      P AS "person",
      P.children AS "children",
      P.hobbies AS "hobbies"

FROM "100_Project/02_dataview/Q23_meeting/Q23_test_data/Meeting/20221217_meeting.md"

FLATTEN this.file.lists AS L
FLATTEN meta(L.header).subpath AS F_subpath
FLATTEN meta(L.header).type AS F_type

WHERE F_type = "header" 
WHERE F_subpath = "Attendees" OR F_subpath = "Host"

FLATTEN L.outlinks AS P
WHERE !contains(P.file.name, "Template")
WHERE contains(P.tags, "person")
```

Screenshots(DQL20): using L.outlinks


2 Likes

I love this, thanks! However, I’m getting a weird error now, though a bit ago I had it working perfectly. Any chance you know what’s going wrong here? See below for the error i’m getting:

I have the person linked to the meeting page like this:
attendee:: [[Person Link]]

That person’s linked page has this in their page:

___
## Interesting details:
notable details:: wow an interesting detail
hobbies:: golf
___
## Relations
spouse:: [[Persons Wife]]
children:: Child1 Name, Child2 Name
colleagues:: 

and my meeting page dataviewjs code is just like yours:

let facts = ["children", "spouse", "notable details", "hobbies"]
displayAttendeeFacts(facts)

function displayAttendeeFacts(facts) {
	let people = getLinkedPeople()

	let tableColumns = ["person"].concat(facts)
	let tableDataFunction = (page) => {
		let personColumn = [dv.fileLink(page.file.name)]
		let factColumns = facts.map(fact => page[fact])
		return personColumn.concat(factColumns)
	}

	if (people.length > 0) {
		dv.table(tableColumns, people.map(tableDataFunction).sort(page => page.file))
	} else {
		dv.paragraph("No people.")
	}
}

function getLinkedPeople() {
	// Get filenames from outgoing links
	let outlinks = dv.current().file.outlinks || []
	let attendees = outlinks.map((link) => link.path.match(/.*\/(.*)\.md/)[1])

	// Retrieve 'people notes' with the same names as outgoing links
	let linkedPeople = [];
	if (attendees.length > 0) {
		linkedPeople = dv.pages('#person')
			.filter(page => {
				let fileName = page.file.name
				let isNotATemplate = !fileName.contains("Template")
				let isAnAttendee = attendees.includes(fileName)
				return isNotATemplate && isAnAttendee
			})
	}

	return linkedPeople
}

Think you can crack the case why I might be getting that “Evaluation Error: TypeError: Cannot read properties of null (reading ‘1’)” ?

I recreated this scenario in a new vault and it worked. Nothing jumps out at me as to why there is a problem. ¯\(ツ)

My advice is:

  1. Restart Obsidian and see if the query works. I’ve noticed that sometimes the Dataview plugin will “glitch out” and only a restart “fixes it”.

  2. If it is still broken, try to isolate the issue…
    a. Recreate this scenario in a new vault
    b. Add one meeting at a time until the problem occurs.
    c. Compare the bad meeting with a good meeting.
    d. You may need to replace values in the bad meeting with those from the good one to identify bad data. Even the frontmatter.

Let me know how you get on. I suspect it is a “bad meeting” file.

Good luck!

Btw Great problem description :+1:

Thanks for getting back to me! I’ll try out those things in a new vault and see what happens.

and yeah, i figure make it as easy as possible for someone to help me!

1 Like