SQLALCHEMY: Wie man Datensätze filtert, die alle Tags in einer vielen-zu-Viele-Beziehung entsprechenPython

Python-Programme
Anonymous
 SQLALCHEMY: Wie man Datensätze filtert, die alle Tags in einer vielen-zu-Viele-Beziehung entsprechen

Post by Anonymous »

Problembeschreibung:
Wir haben ein Kontaktverwaltungssystem, bei dem Kontakte mit Hashtags markiert werden können (z. B. #work , #Personal ). Das System muss Kontakte basierend auf Hashtags filtern, wobei ein Kontakt nur dann zurückgegeben werden sollte, wenn er alle angeforderten Hashtags enthält. >

Code: Select all

# Three test contacts:
- Alice: tagged with ["#test", "#dev"]
- Bob: tagged with ["#dev"]
- Charlie: tagged with ["#prod"]
Erwartete Verhalten:
  • Beim Filtern für #Test → nur Alice sollte zurückgegeben werden (count = 1)
  • Beim Filtern für #Dev → Sowohl Alice und Bob sollten zurückgegeben werden (count = 2)
  • Beim Filtern für #Test sollte #dev → nur Alice zurückgegeben werden (count = 1)
Datenbankschema :

Code: Select all

- 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] Problementwicklung: < /strong> < /p>
[list]
[*]  Erster Versuch - Einfacher Join (fehlgeschlagen) [/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)
)
Warum es fehlgeschlagen ist: Dieser Ansatz gab jeden Kontakt zurück, der mindestens einen passenden Hashtag hatte und uns eine oder eine Beziehung anstelle von und. />
[*] Zweiter Versuch - existiert die Bedingungen (fehlgeschlagen) < /strong> < /li>
< /ol>

Code: Select all

# 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))
Warum es fehlgeschlagen ist: [/b] Während dies versuchte, für jedes Tag einzeln zu prüfen, hatte es Probleme mit der Unterabbildungsstruktur und gab immer noch nicht die richtigen Ergebnisse zurück. < /p>

Aktueller Versuch - Gruppe mit (noch nicht funktioniert) < /strong> < /li>
< /ol>

Code: Select all

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)))
Warum es immer noch nicht funktioniert: [/b] Während dieser Ansatz theoretisch korrekt erscheint (Gruppieren durch Kontakt und Zählen verschiedener Matching -Tags), erzeugt es nicht die erwarteten Ergebnisse in unseren Tests . Beim Filtern für #Test sollte es nur Alice zurückgeben, jedoch alle Kontakte zurückgeben. />

Code: Select all

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)
Wir brauchen Hilfe, um herauszufinden, warum diese Gruppe nach Ansatz die Kontakte nicht korrekt filtert oder ob es einen besseren Ansatz gibt, um diese All-Tag-Filterung in Sqlalchemy zu erreichen.
< BR /> Die ideale Lösung sollte: < /p>

Handeln Sie die Einzelhashtag -Filterung korrekt. (Und Logik)
[*] Seien Sie effizient mit größeren Datensätzen
[*] Arbeiten Sie mit SQLite (für Tests) und seien Sie mit anderen SQL -Datenbanken kompatibel < Br /> < /ol>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post