Sure. Following are the models I am using:
class Project(models.Model):
name = models.CharField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Brand(models.Model):
name = models.CharField()
domain = models.CharField()
is_own = models.BooleanField()
project = models.ForeignKey(Project, on_delete=models.CASCADE)
class Meta:
constraints = [
UniqueConstraint(
fields=("name", "project"), name="UQ_brand_name_project_id"
),
]
class PromptSet(models.Model):
is_active = models.BooleanField(default=True)
name = models.CharField()
project = models.ForeignKey(Project, on_delete=models.CASCADE)
class Conversation(models.Model):
prompt_set = models.ForeignKey(PromptSet, on_delete=models.CASCADE)
class Prompt(models.Model):
name = models.CharField(null=True)
content = models.TextField()
level = models.IntegerField()
conversation = models.ForeignKey(
Conversation, on_delete=models.CASCADE, related_name="prompts"
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=("level", "conversation"),
name="UQ_level_conversation",
)
]
class Evaluation(models.Model):
ai_model = models.CharField(choices=AIModelsEnum.choices)
datetime = models.DateTimeField()
ai_response = models.TextField()
prompt = models.ForeignKey(Prompt, on_delete=models.CASCADE)
brand = models.ManyToManyField(
Brand,
through="EvaluationCount",
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=("ai_model", "datetime", "prompt"),
name="UQ_ai_model_datetime_prompt",
)
]
class EvaluationCount(models.Model):
name_count = models.IntegerField()
source_count = models.IntegerField()
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, null=True)
evaluation = models.ForeignKey(Evaluation, on_delete=models.CASCADE)
class Meta:
constraints = [
models.UniqueConstraint(
fields=(
"brand",
"evaluation",
),
name="UQ_brand_evaluation",
)
]
currently django generates following query:
SELECT
"prompt_sets_conversation"."prompt_set_id",
"prompts_evaluation"."ai_model",
"prompt_sets_promptset"."name",
SUM("prompts_evaluationcount"."name_count") AS "total_brand_mentions",
SUM(
CASE
WHEN "projects_brand"."is_own" THEN "prompts_evaluationcount"."name_count"
ELSE 0
END
) AS "own_brand_mentions",
SUM("prompts_evaluationcount"."source_count") AS "total_source_mentions",
SUM(
CASE
WHEN "projects_brand"."is_own" THEN "prompts_evaluationcount"."source_count"
ELSE 0
END
) AS "own_source_mentions"
FROM
"prompts_evaluation"
INNER JOIN "prompts_prompt" ON (
"prompts_evaluation"."prompt_id" = "prompts_prompt"."id"
)
INNER JOIN "prompt_sets_conversation" ON (
"prompts_prompt"."conversation_id" = "prompt_sets_conversation"."id"
)
INNER JOIN "prompt_sets_promptset" ON (
"prompt_sets_conversation"."prompt_set_id" = "prompt_sets_promptset"."id"
)
INNER JOIN "projects_project" ON (
"prompt_sets_promptset"."project_id" = "projects_project"."id"
)
LEFT OUTER JOIN "prompts_evaluationcount" ON (
"prompts_evaluation"."id" = "prompts_evaluationcount"."evaluation_id"
)
LEFT OUTER JOIN "projects_brand" ON (
"prompts_evaluationcount"."brand_id" = "projects_brand"."id"
)
WHERE
(
"prompts_evaluation"."datetime" = (
SELECT
MAX(U0."datetime") AS "latest_datetime"
FROM
"prompts_evaluation" U0
INNER JOIN "prompts_prompt" U1 ON (U0."prompt_id" = U1."id")
INNER JOIN "prompt_sets_conversation" U2 ON (U1."conversation_id" = U2."id")
WHERE
(
U0."ai_model" = ("prompts_evaluation"."ai_model")
AND U2."prompt_set_id" = ("prompt_sets_conversation"."prompt_set_id")
)
GROUP BY
U2."prompt_set_id",
U0."ai_model"
)
AND "prompt_sets_conversation"."prompt_set_id" IN (
SELECT
U0."id"
FROM
"prompt_sets_promptset" U0
INNER JOIN "prompt_sets_conversation" U1 ON (U0."id" = U1."prompt_set_id")
INNER JOIN "prompt_sets_promptset" U2 ON (U1."prompt_set_id" = U2."id")
WHERE
U2."project_id" = 17
LIMIT
2
)
AND "projects_project"."user_id" = 15
AND "prompt_sets_promptset"."project_id" = 17
)
GROUP BY
"prompt_sets_conversation"."prompt_set_id",
"prompts_evaluation"."ai_model",
"prompt_sets_promptset"."name"
This query is taking about a minute to execute. you can see the result of explain analyze of it here.
But the same output can be generated by following SQL query that I have manually written:
SELECT
"prompt_sets_conversation"."prompt_set_id",
"prompts_evaluation"."ai_model",
"prompt_sets_promptset"."name",
SUM("prompts_evaluationcount"."name_count") AS "total_brand_mentions",
SUM(
CASE
WHEN "projects_brand"."is_own" THEN "prompts_evaluationcount"."name_count"
ELSE 0
END
) AS "own_brand_mentions",
SUM("prompts_evaluationcount"."source_count") AS "total_source_mentions",
SUM(
CASE
WHEN "projects_brand"."is_own" THEN "prompts_evaluationcount"."source_count"
ELSE 0
END
) AS "own_source_mentions"
FROM
PROMPTS_EVALUATION
INNER JOIN "prompts_prompt" ON (
"prompts_evaluation"."prompt_id" = "prompts_prompt"."id"
)
INNER JOIN "prompt_sets_conversation" ON (
"prompts_prompt"."conversation_id" = "prompt_sets_conversation"."id"
)
INNER JOIN "prompt_sets_promptset" ON (
"prompt_sets_conversation"."prompt_set_id" = "prompt_sets_promptset"."id"
)
INNER JOIN (
SELECT
PROMPT_SETS_PROMPTSET.ID,
AI_MODEL,
MAX(DATETIME)
FROM
PROMPTS_EVALUATION
INNER JOIN "prompts_prompt" ON (
"prompts_evaluation"."prompt_id" = "prompts_prompt"."id"
)
INNER JOIN "prompt_sets_conversation" ON (
"prompts_prompt"."conversation_id" = "prompt_sets_conversation"."id"
)
INNER JOIN (
SELECT
PROMPT_SETS_PROMPTSET.*
FROM
PROMPT_SETS_PROMPTSET
INNER JOIN "projects_project" ON (
"prompt_sets_promptset"."project_id" = "projects_project"."id"
)
WHERE
PROJECTS_PROJECT.ID = 17
ORDER BY
PROMPT_SETS_PROMPTSET.ID
LIMIT
2
) "prompt_sets_promptset" ON (
"prompt_sets_conversation"."prompt_set_id" = "prompt_sets_promptset"."id"
)
GROUP BY
PROMPT_SETS_PROMPTSET.ID,
AI_MODEL
) "temp" ON (
TEMP.ID = PROMPT_SETS_PROMPTSET.ID
AND TEMP.MAX = PROMPTS_EVALUATION.DATETIME
AND TEMP.AI_MODEL = PROMPTS_EVALUATION.AI_MODEL
)
INNER JOIN "projects_project" ON (
"prompt_sets_promptset"."project_id" = "projects_project"."id"
)
LEFT OUTER JOIN "prompts_evaluationcount" ON (
"prompts_evaluation"."id" = "prompts_evaluationcount"."evaluation_id"
)
LEFT OUTER JOIN "projects_brand" ON (
"prompts_evaluationcount"."brand_id" = "projects_brand"."id"
)
WHERE
PROJECTS_PROJECT.ID = 17
AND "projects_project"."user_id" = 15
GROUP BY
"prompt_sets_conversation"."prompt_set_id",
"prompts_evaluation"."ai_model",
"prompt_sets_promptset"."name"
This query gets executed in milliseconds. you can see the output of explain analyze of it here.