Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres Full Text search. #1

Merged
merged 55 commits into from
Jul 10, 2024
Merged

Postgres Full Text search. #1

merged 55 commits into from
Jul 10, 2024

Conversation

cyrillkuettel
Copy link
Member

@cyrillkuettel cyrillkuettel commented Jul 2, 2024

The search works.

  • mypy errors still need to be adressed
  • Some UI polishing work for the display of the result
  • ...

image

In `SearchCollection`, the ts_query is currently created every time
the do_search method is called. This is unnecessary if ts_query only
depends on the search term, which is not expected to change throughout
the lifetime of the object.
We need to update this in the background using the event API from
sqlalchemy directly. The reason for this was that before we used
`@observes` for the files, this  seems to not work in some cases if used
in combination with `asssociated` 💡
@cyrillkuettel cyrillkuettel requested a review from Daverball July 4, 2024 01:59
Copy link
Member

@Daverball Daverball left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good, there's some small issues about ORM event and markup handling.

src/privatim/__init__.py Outdated Show resolved Hide resolved
src/privatim/models/__init__.py Outdated Show resolved Hide resolved
src/privatim/models/__init__.py Outdated Show resolved Hide resolved
@@ -242,6 +245,7 @@ def descriptor(cls: type['Base']) -> Mapped[list[_M]]:
return relationship(
argument=associated_cls,
secondary=association_table,
back_populates=back_populates,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should never be None. I think you messed things up by inheriting from File, but rather than making File polymorphic you used a different table. Associable assumes polymorphism, i.e. the class that's before Associable in the MRO is considered the polymorphic base, so if you want to share attributes between both file types then you need to split those out into a common abstract base class (__abstract__ = True without setting __tablename__) that both File and SearchableFile inherit from, as well as Associable at the same time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will mean you will need to query the abstract base class if you want to query both File and SearchableFile at the same time. But it's probably good to be explicit about this anyways, since this implicitly involves a union of two distinct tables.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some context: I added this because @observes (from sqlalchemy_utils) didn't work for files, which is what I initially planned to use instead of sqlalchemy's event. I saw the comment in onegov about this potentially being an issue and wanted to check if this would fix it.

This is sort of from onegov, but a more simpler version, I noticted we also set back_populates = None in onegov, though I'm not sure I fully grasp the implications.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I first used @observes as seen here. The docstring migrated then and silently diverged from it's original meaning

d692261#diff-33826b0cae4b335e638aec7708f9e99573759086e592e1a4a331d6596d63fb81R86-R96

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

observes didn't work because you broke the back reference with your inheritance structure of SearchableFile using its own table.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More concretely, if you look more closely at Associable you'll notice that all the links are put on the association_base_cls which is going to be File both for File and SearchableFile. So right now even the links on SearchableFile are put into File, so the links property is incorrect.

I assume you got rid of the whole logic about backref and back_populates from onegov, because SQLAlchemy 2.0 emits a warning when using backref instead of back_populates. But this is one of the cases where you do need to use backref so you get a proper bidirectional relationship that can be followed by the @observes decorator.

What the decorator does under the hood is, it looks at the reverse relationship and installs a hook on the related model that looks at changes on the reverse relationship. So it properly does the backwards-logic thing, where the changes that would trigger this observer don't happen in this table but rather in a different table.

src/privatim/views/search.py Outdated Show resolved Hide resolved
src/privatim/views/search.py Outdated Show resolved Hide resolved
src/privatim/views/search.py Outdated Show resolved Hide resolved
src/privatim/views/search.py Show resolved Hide resolved
src/privatim/views/templates/activities.pt Outdated Show resolved Hide resolved
src/privatim/views/templates/search_results.pt Outdated Show resolved Hide resolved
Copy link
Member

@Daverball Daverball left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The associable thing is still not quite right, but you're almost there

src/privatim/orm/abstract.py Outdated Show resolved Hide resolved
src/privatim/models/file.py Outdated Show resolved Hide resolved
src/privatim/models/file.py Outdated Show resolved Hide resolved
src/privatim/models/file.py Show resolved Hide resolved
src/privatim/orm/abstract.py Outdated Show resolved Hide resolved
Copy link

codecov bot commented Jul 9, 2024

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@cyrillkuettel
Copy link
Member Author

Summary:

  • fixed re-occcouring mypy errors
  • Add ts_rank: More weight can be given to a column if that column is particularly important (for example the title)
  • Come back full circle: Add the observes again (syntactic sugar for sqlalchemy event). We keep it simple and don't use observes on the SearchableAssociatedFiles which introduces complexity
  • MarkupText
  • Adjust the download view to also work with the new SearchableFile
  • Cleanup between tests: Fix teardown in function-scoped 'client' pytest fixture (was ForeignKey error). Just drop everything with Base.metadata.create_all(engine)

@cyrillkuettel cyrillkuettel merged commit f5057b1 into develop Jul 10, 2024
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants