Skip to content

Commit

Permalink
Fix text-based users search
Browse files Browse the repository at this point in the history
  • Loading branch information
bkis committed Sep 18, 2024
1 parent 953bf05 commit 3b6fab0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
9 changes: 0 additions & 9 deletions Tekst-API/tekst/models/user.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from datetime import datetime
from typing import Annotated, Literal, get_args

import pymongo

from beanie import Document, PydanticObjectId
from fastapi_users import (
schemas,
Expand Down Expand Up @@ -151,13 +149,6 @@ class Settings(BeanieBaseUser.Settings):
name = "users"
indexes = BeanieBaseUser.Settings.indexes + [
IndexModel("username", unique=True),
IndexModel(
[
("username", pymongo.TEXT),
("name", pymongo.TEXT),
("affiliation", pymongo.TEXT),
],
),
]

is_active: bool = _cfg.security.users_active_by_default
Expand Down
31 changes: 27 additions & 4 deletions Tekst-API/tekst/routers/users.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re

from typing import Annotated

from beanie import PydanticObjectId
from beanie.operators import NE, Eq, Or, Text
from beanie.operators import NE, Eq, Or, RegEx
from fastapi import APIRouter, Depends, Path, Query, Request, status

from tekst import errors
Expand All @@ -21,6 +23,26 @@
from tekst.utils import validators as val


def _get_user_text_query(
query_str: str,
*,
min_q_length: int = 1,
empty_q_matches_all: bool = True,
) -> dict:
q = re.sub(r"\W", "", query_str or "").strip()
if not q or len(q) < min_q_length:
if empty_q_matches_all:
return {}
else:
return Eq(UserDocument.id, 0)
else:
return Or(
RegEx(UserDocument.username, q, "i"),
RegEx(UserDocument.name, q, "i"),
RegEx(UserDocument.affiliation, q, "i"),
)


router = APIRouter(
prefix="/users",
tags=["users"],
Expand Down Expand Up @@ -126,7 +148,7 @@ async def find_users(
) -> UsersSearchResult:
# construct DB query
db_query = [
Text(query) if query else {},
_get_user_text_query(query),
Or(
Eq(UserDocument.is_active, is_active)
if is_active
Expand Down Expand Up @@ -259,19 +281,20 @@ async def find_public_users(

# construct DB query
db_query = [
Text(query) if query else {},
_get_user_text_query(query),
Eq(UserDocument.is_active, True),
]

# count total possible hits
# (yeah, MongoDB doesn't give us the total for a skipped query)
total = await UserDocument.find(*db_query).count()

# return actual paginated, sorted restults
pgn = PaginationSettings(page=page, page_size=page_size)
return PublicUsersSearchResult(
users=(
await UserDocument.find(*db_query)
.sort(+UserDocument.name)
.sort(+UserDocument.name, +UserDocument.username)
.skip(pgn.mongo_skip())
.limit(pgn.mongo_limit())
.to_list()
Expand Down

0 comments on commit 3b6fab0

Please sign in to comment.