algos: introduce last_n_per_pubkey_from_tags

This function creates filters for the base our first algo in Damus:

Called "last N note per pubkey". I don't have a better name for it.

This function generates a query in the form:

[
  {"authors": ["author_a"], "limit": 1, "kinds": [1]
, {"authors": ["author_b"], "limit": 1, "kinds": [1]
, {"authors": ["author_c"], "limit": 1, "kinds": [1]
, {"authors": ["author_c"], "limit": 1, "kinds": [1]
  ...
]

Due to an unfortunate restriction currently in nostrdb and strfry, we
can only do about 16 to 20 of these at any given time. I have made
this limit configurable in strfry[1]. I just need to do the same in
nostrdb now.

[1] https://github.com/hoytech/strfry/pull/133

Changelog-Added: Add last_n_per_pubkey_from_tags algo function
This commit is contained in:
William Casarin
2024-12-26 09:38:56 -08:00
parent 9dd33d5c5b
commit 7afe3b7d7c

View File

@@ -190,6 +190,60 @@ impl FilteredTags {
}
}
/// Create a "last N notes per pubkey" query.
pub fn last_n_per_pubkey_from_tags(
note: &Note,
kind: u64,
notes_per_pubkey: u64,
) -> Result<Vec<Filter>> {
let mut filters: Vec<Filter> = vec![];
for tag in note.tags() {
// TODO: fix arbitrary MAX_FILTER limit in nostrdb
if filters.len() == 15 {
break;
}
if tag.count() < 2 {
continue;
}
let t = if let Some(t) = tag.get_unchecked(0).variant().str() {
t
} else {
continue;
};
if t == "p" {
let author = if let Some(author) = tag.get_unchecked(1).variant().id() {
author
} else {
continue;
};
let mut filter = Filter::new();
filter.start_authors_field()?;
filter.add_id_element(author)?;
filter.end_field();
filters.push(filter.kinds([kind]).limit(notes_per_pubkey).build());
} else if t == "t" {
let hashtag = if let Some(hashtag) = tag.get_unchecked(1).variant().str() {
hashtag
} else {
continue;
};
let mut filter = Filter::new();
filter.start_tags_field('t')?;
filter.add_str_element(hashtag)?;
filter.end_field();
filters.push(filter.kinds([kind]).limit(notes_per_pubkey).build());
}
}
Ok(filters)
}
/// Create a filter from tags. This can be used to create a filter
/// from a contact list
pub fn filter_from_tags(