SQLalchemy: Как фильтровать записи, которые соответствуют всем тегам в отношениях многих ко многимPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 SQLalchemy: Как фильтровать записи, которые соответствуют всем тегам в отношениях многих ко многим

Сообщение Anonymous »

Описание проблемы:
У нас есть система управления контактами, где контакты могут быть помечены хэштегами (например, #work , #personal ). Система должна отфильтровать контакты на основе хэштегов, где контакт должен быть возвращен только в том случае, если в нем есть все запрошенные хэштеги. >

Код: Выделить всё

# Three test contacts:
- Alice: tagged with ["#test", "#dev"]
- Bob: tagged with ["#dev"]
- Charlie: tagged with ["#prod"]
ожидаемое поведение:
  • При фильтрации для #test → только Алиса должна быть возвращена (count = 1)
  • При фильтрации для #dev → Алиса и Боб должны быть возвращены (count = 2)
  • При фильтрации для #тест #dev → только Алиса должна быть возвращена (count = 1)
схема базы данных :

Код: Выделить всё

- contacts: Main contacts table with id, name, etc.
- hashtags: Table storing unique hashtags with id, name, entity_type
- contact_hashtags: Junction table linking contacts to hashtags
- contact_id (FK to contacts)
- hashtag_id (FK to hashtags)
< /code>
[b] evolution: < /strong> < /p>
[list]
[*]  Первая попытка - Simple Join (не удалось) [/b]
[/list]
# This returned contacts with ANY of the hashtags instead of ALL
query = query.join(contact_hashtags).join(Hashtag).filter(
Hashtag.name.in_(tag_list)
)
Почему он не удался: Этот подход вернул любой контакт, который имел хотя бы один сопоставленный хэштег, давая нам или отношения вместо и.

[*] вторая попытка - существует условия (не удастся) < /strong> < /li>
< /ol>

Код: Выделить всё

# Created EXISTS conditions for each hashtag
for tag in tag_list:
exists_condition = (
db.query(contact_hashtags)
.join(Hashtag)
.filter(
contact_hashtags.c.contact_id == Contact.id,
Hashtag.entity_type == EntityType.CONTACT,
Hashtag.name == tag
)
.exists()
)
query = query.filter(sa.exists(exists_condition))
Почему это не удалось: [/b], в то время как это пыталось проверить на каждую тег индивидуально, у него были проблемы со структурой подказки и до сих пор не вернули правильные результаты. /p>

текущая попытка - группа с помощью (все еще не работает) < /strong> < /li>
< /ol>

Код: Выделить всё

matching_ids = (
db.query(contact_hashtags.c.contact_id)
.join(Hashtag)
.filter(
Hashtag.entity_type == EntityType.CONTACT,
Hashtag.name.in_(tag_list)
)
.group_by(contact_hashtags.c.contact_id)
.having(sa.func.count(sa.distinct(Hashtag.name)) == len(tag_list))
).subquery()

query = query.filter(Contact.id.in_(db.query(matching_ids.c.contact_id)))
Почему он все еще не работает: [/b], хотя этот подход кажется теоретически правильным (группировка путем контакта и подсчета отдельных соответствующих тегов), он не дает ожидаемых результатов в наших тестах Полем При фильтрации для #test она должна возвращать только Алису, но возвращает все контакты. />

Код: Выделить всё

def test_list_contacts_hashtag_filter(client: TestClient, db_session: Session):
# Setup:
# Alice: ["#test", "#dev"]
# Bob: ["#dev"]
# Charlie: ["#prod"]

# This test fails:
response = client.get("/api/contacts?hashtags=#test")
data = response.json()
assert data["total_count"] == 1  # Expecting only Alice
# But we're getting total_count == 3 (all contacts)
Нам нужна помощь в выяснении, почему эта группа по подходу не правильно отфильтровала контакты, или если есть лучший подход для достижения этой фильтрации All-Tags в Sqlalchemy.
Идеальное решение должно: < /p>

Правильно обрабатывать одиночную хэштегфильтра (И логика)
[*] Будьте эффективны с более крупными наборами данных
[*] Работать с SQLite (для тестов) и совместимы с другими базами данных SQL < Br /> < /ol>

Подробнее здесь: https://stackoverflow.com/questions/794 ... y-relation
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»