[IMP] website: filter out unpublished records for non internal users
Issue: Search on website has a big performance issue because the database has too many product_template. Analyze : The website search mechanism has hardcoded sql query. And the generic query don't have any filtering. Which lead to make a expensive search (similarity) on the whole product_template even if the products are not published and then displayed to the user. Fix : Filter the is_published field in the generic website method when the model has a 'is_published' field and the request is not done by a user (thus for customers or portal users). Note: The internal user is still able to search on unpublished product.Thus have no performance improvement. Benchmark: | SQL Query | # Input data | Before PR | After PR | |:---------:|:------------:|:---------:|:--------:| |General best_similarity |700000 products (161 published) | 12.65 s | 0.12 s | |FROM ir_translation|2,796,000 ir_translation | 6.338 s (586k hit) | 0.091 s (185 hit) | Related task: task-3473786 Related ticket: opw-3418457 closes odoo/odoo#136080 X-original-commit: fcb968836a2d0e49516fe3ecb23dde61f4597749 Signed-off-by: Romain Derie (rde) <rde@odoo.com>
This commit is contained in:
@@ -1769,6 +1769,18 @@ class Website(models.Model):
|
||||
similarities=sql.SQL(', ').join(similarities)
|
||||
)
|
||||
|
||||
where_clause = sql.SQL("")
|
||||
# Filter unpublished records for portal and public user for
|
||||
# performance.
|
||||
# TODO: Same for `active` field?
|
||||
filter_is_published = (
|
||||
'is_published' in model._fields
|
||||
and model._fields['is_published'].base_field.model_name == model_name
|
||||
and not self.env.user.has_group('base.group_user')
|
||||
)
|
||||
if filter_is_published:
|
||||
where_clause = sql.SQL("WHERE is_published")
|
||||
|
||||
from_clause = sql.SQL("FROM {table}").format(table=sql.Identifier(model._table))
|
||||
# Specific handling for fields being actually part of another model
|
||||
# through the `inherits` mechanism.
|
||||
@@ -1787,12 +1799,14 @@ class Website(models.Model):
|
||||
query = sql.SQL("""
|
||||
SELECT {table}.id, {best_similarity} AS _best_similarity
|
||||
{from_clause}
|
||||
{where_clause}
|
||||
ORDER BY _best_similarity desc
|
||||
LIMIT 1000
|
||||
""").format(
|
||||
table=sql.Identifier(model._table),
|
||||
best_similarity=best_similarity,
|
||||
from_clause=from_clause,
|
||||
where_clause=where_clause,
|
||||
)
|
||||
self.env.cr.execute(query, {'search': search})
|
||||
ids = {row[0] for row in self.env.cr.fetchall() if row[1] and row[1] >= similarity_threshold}
|
||||
|
||||
Reference in New Issue
Block a user