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

Combining rows_where() and search() to limit which rows are searched #441

Closed
betatim opened this issue Jun 2, 2022 · 4 comments
Closed

Comments

@betatim
Copy link

betatim commented Jun 2, 2022

What is the right way to limit a full text search query to some rows of a table?

For example, I have a table that contains the following columns: title, content, owner (each row represents a document). The owner column is a username. It feels right to store all documents in one table, instead of having one table per owner. In particular because I'd like to full text search all documents, only documents owned by one user and documents owned by a set of users.

I tried to combine .rows_where("owner = ?", "1234") and .search() from the Table class but I don't think that is meant to work. I discovered .search_sql() as a way to generate the FTS SQL statement. By hand I can edit it to add a AND [original].[owner] = :owner to the where clause. This seems to do what I want.

My two questions:

  1. is adding a AND ... to the where clause actually the right thing to do or should I be doing something else (my SQL skills are low)?
  2. is there a built-in to sqlite-utils way to achieve this?

Right now I am thinking I will make my own version of search_sql() that generates a query that contains an additional owner = :owner for my particular use-case.

Bonus question: is this generally useful/something to add to sqlite-utils or too niche?

@simonw
Copy link
Owner

simonw commented Jun 13, 2022

Yeah, at the moment the best way to do this is with search_sql(), but you're right it really isn't very intuitive.

Here's how I would do this, using a CTE trick to combine the queries:

search_sql = db["articles"].search_sql(columns=["title", "author"]))
sql = f"""
with search_results as ({search_sql})
select * from search_results where owner = :owner
"""
results = db.query(sql, {"query": "my search query", "owner": "my owner"})

I'm not sure if sqlite-utils should ever evolve to provide a better way of doing this kind of thing to be honest - if it did, it would turn into more of an ORM. Something like PeeWee may be a better option here.

@simonw simonw closed this as completed Jun 14, 2022
@simonw
Copy link
Owner

simonw commented Jun 14, 2022

Actually I have a thought for something that could help here: I could add a mechanism for inserting additional where filters and parameters into that .search() method.

@simonw simonw reopened this Jun 14, 2022
@betatim
Copy link
Author

betatim commented Jun 14, 2022

That would be handy (additional where filters) but I think the trick with the with statement is already an order of magnitude better than what I had thought of, so my problem is solved by it (plus I got to learn about with today!)

@simonw simonw closed this as completed in 1b09538 Jun 14, 2022
@simonw
Copy link
Owner

simonw commented Jun 14, 2022

I added where= and where_args= parameters to that .search() method - updated documentation is here: https://sqlite-utils.datasette.io/en/latest/python-api.html#searching-with-table-search

simonw added a commit that referenced this issue Jun 15, 2022
simonw added a commit that referenced this issue Jun 15, 2022
simonw added a commit that referenced this issue Jul 15, 2022
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

No branches or pull requests

2 participants