У нас есть система управления контактами, где контакты могут быть помечены хэштегами (например, #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))
текущая попытка - группа с помощью (все еще не работает) < /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)))
Код: Выделить всё
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)
Идеальное решение должно: < /p>
Правильно обрабатывать одиночную хэштегфильтра (И логика)
[*] Будьте эффективны с более крупными наборами данных
[*] Работать с SQLite (для тестов) и совместимы с другими базами данных SQL < Br /> < /ol>
Подробнее здесь: https://stackoverflow.com/questions/794 ... y-relation