TagIndex.pm 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package Trog::SQLite::TagIndex;
  2. use strict;
  3. use warnings;
  4. no warnings 'experimental';
  5. use feature qw{signatures};
  6. use List::Util qw{uniq};
  7. use Trog::SQLite;
  8. =head1 Trog::SQLite::TagIndex
  9. An SQLite3 index of posts by tag.
  10. Used to speed up the flat-file data model.
  11. =head1 FUNCTIONS
  12. =cut
  13. sub posts_for_tags ($limit=0, @tags) {
  14. my $dbh = _dbh();
  15. my $clause = @tags ? "WHERE tag IN (".join(',' ,(map {'?'} @tags)).")" : '';
  16. if ($limit) {
  17. $clause .= "LIMIT ?";
  18. push(@tags,$limit);
  19. }
  20. my $rows = $dbh->selectall_arrayref("SELECT id FROM posts $clause",{ Slice => {} }, @tags);
  21. return () unless ref $rows eq 'ARRAY' && @$rows;
  22. return map { $_->{id} } @$rows;
  23. }
  24. sub add_post ($post,$data_obj) {
  25. my $dbh = _dbh();
  26. return build_index($data_obj,[$post]);
  27. }
  28. sub remove_post ($post) {
  29. my $dbh = _dbh();
  30. return $dbh->do("DELETE FROM posts_index WHERE post_id=?", undef, $post->{id});
  31. }
  32. sub build_index($data_obj,$posts=[]) {
  33. my $dbh = _dbh();
  34. $posts = $data_obj->read({ limit => 0, acls => ['admin'] }) unless @$posts;
  35. my @tags = uniq map { @{$_->{tags}} } @$posts;
  36. Trog::SQLite::bulk_insert($dbh,'tag', ['name'], 'IGNORE', @tags);
  37. my $t = $dbh->selectall_hashref("SELECT id,name FROM tag", 'name');
  38. foreach my $k (keys(%$t)) { $t->{$k} = $t->{$k}->{id} };
  39. Trog::SQLite::bulk_insert($dbh,'posts_index',[qw{post_id tag_id}], 'IGNORE', map {
  40. my $subj = $_;
  41. map { ( $subj->{id}, $t->{$_} ) } @{$subj->{tags}}
  42. } @$posts );
  43. }
  44. # Ensure the db schema is OK, and give us a handle
  45. sub _dbh {
  46. my $file = 'schema/flatfile.schema';
  47. my $dbname = "data/posts.db";
  48. return Trog::SQLite::dbh($file,$dbname);
  49. }
  50. 1;