Add --max-distance for recursive link filtering options

pull/6/head
Mickaël Menu 3 years ago
parent 2111deb88d
commit d9d5fe1730
No known key found for this signature in database
GPG Key ID: 53D73664CD359895

@ -342,7 +342,7 @@ func (d *NoteDAO) findRows(opts note.FinderOpts) (*sql.Rows, error) {
groupById := false
args := make([]interface{}, 0)
setupLinkFilter := func(paths []string, forward, negate bool, recursive bool) error {
setupLinkFilter := func(paths []string, forward, negate, recursive bool, maxDistance int) error {
ids, err := d.findIdsByPathPrefixes(paths)
if err != nil {
return err
@ -371,7 +371,12 @@ func (d *NoteDAO) findRows(opts note.FinderOpts) (*sql.Rows, error) {
// Credit to https://inviqa.com/blog/storing-graphs-database-sql-meets-social-network
links_src = "links_transitive_closure"
orderTerms = append(orderTerms, alias+".distance")
cteClauses = append(cteClauses, `WITH RECURSIVE links_transitive_closure(source_id, target_id, title, snippet, distance, path) AS (
if maxDistance == 0 {
maxDistance = 1000
}
cteClauses = append(cteClauses, fmt.Sprintf(`WITH RECURSIVE links_transitive_closure(source_id, target_id, title, snippet, distance, path) AS (
SELECT source_id, target_id, title, snippet,
1 AS distance,
source_id || '.' || target_id || '.' AS path
@ -385,8 +390,8 @@ func (d *NoteDAO) findRows(opts note.FinderOpts) (*sql.Rows, error) {
FROM links AS l
JOIN links_transitive_closure AS tc
ON l.source_id = tc.target_id
WHERE tc.path NOT LIKE '%' || l.target_id || '.%'
)`)
WHERE tc.distance < %d AND tc.path NOT LIKE '%%' || l.target_id || '.%%'
)`, maxDistance))
}
if !negate {
@ -439,13 +444,13 @@ func (d *NoteDAO) findRows(opts note.FinderOpts) (*sql.Rows, error) {
whereExprs = append(whereExprs, strings.Join(globs, " AND "))
case note.LinkedByFilter:
err := setupLinkFilter(filter.Paths, false, filter.Negate, filter.Recursive)
err := setupLinkFilter(filter.Paths, false, filter.Negate, filter.Recursive, filter.MaxDistance)
if err != nil {
return nil, err
}
case note.LinkingToFilter:
err := setupLinkFilter(filter.Paths, true, filter.Negate, filter.Recursive)
err := setupLinkFilter(filter.Paths, true, filter.Negate, filter.Recursive, filter.MaxDistance)
if err != nil {
return nil, err
}

@ -528,6 +528,20 @@ func TestNoteDAOFindLinkedByRecursive(t *testing.T) {
)
}
func TestNoteDAOFindLinkedByRecursiveWithMaxDistance(t *testing.T) {
testNoteDAOFindPaths(t,
note.FinderOpts{
Filters: []note.Filter{note.LinkedByFilter{
Paths: []string{"log/2021-01-04.md"},
Negate: false,
Recursive: true,
MaxDistance: 2,
}},
},
[]string{"index.md", "f39c8.md"},
)
}
func TestNoteDAOFindLinkedByWithSnippets(t *testing.T) {
testNoteDAOFind(t,
note.FinderOpts{
@ -612,6 +626,20 @@ func TestNoteDAOFindLinkingToRecursive(t *testing.T) {
)
}
func TestNoteDAOFindLinkingToRecursiveWithMaxDistance(t *testing.T) {
testNoteDAOFindPaths(t,
note.FinderOpts{
Filters: []note.Filter{note.LinkingToFilter{
Paths: []string{"log/2021-01-04.md"},
Negate: false,
Recursive: true,
MaxDistance: 2,
}},
},
[]string{"log/2021-01-03.md", "f39c8.md"},
)
}
func TestNoteDAOFindNotLinkingTo(t *testing.T) {
testNoteDAOFindPaths(t,
note.FinderOpts{

@ -24,6 +24,7 @@ type Filtering struct {
LinkingTo []string `help:"Only the notes linking to the given notes" placeholder:"<path>" short:"L"`
NotLinkedBy []string `help:"Only the notes not linked by the given notes" placeholder:"<path>"`
NotLinkingTo []string `help:"Only the notes not linking to the given notes" placeholder:"<path>"`
MaxDistance int `help:"Maximum distance between two linked notes"`
Orphan bool `help:"Only the notes which don't have any other note linking to them"`
Exclude []string `help:"Excludes notes matching the given file path pattern from the list" short:"x" placeholder:"<glob>"`
Recursive bool `help:"Follow links recursively" short:"r"`
@ -128,18 +129,20 @@ func NewFinderOpts(zk *zk.Zk, filtering Filtering, sorting Sorting) (*note.Finde
linkedByPaths, ok := relPaths(zk, filtering.LinkedBy)
if ok {
filters = append(filters, note.LinkedByFilter{
Paths: linkedByPaths,
Negate: false,
Recursive: filtering.Recursive,
Paths: linkedByPaths,
Negate: false,
Recursive: filtering.Recursive,
MaxDistance: filtering.MaxDistance,
})
}
linkingToPaths, ok := relPaths(zk, filtering.LinkingTo)
if ok {
filters = append(filters, note.LinkingToFilter{
Paths: linkingToPaths,
Negate: false,
Recursive: filtering.Recursive,
Paths: linkingToPaths,
Negate: false,
Recursive: filtering.Recursive,
MaxDistance: filtering.MaxDistance,
})
}

@ -42,16 +42,18 @@ type ExcludePathFilter []string
// LinkedByFilter is a note filter used to select notes being linked by another one.
type LinkedByFilter struct {
Paths []string
Negate bool
Recursive bool
Paths []string
Negate bool
Recursive bool
MaxDistance int
}
// LinkingToFilter is a note filter used to select notes being linked by another one.
type LinkingToFilter struct {
Paths []string
Negate bool
Recursive bool
Paths []string
Negate bool
Recursive bool
MaxDistance int
}
// OrphanFilter is a note filter used to select notes having no other notes linking to them.

Loading…
Cancel
Save