mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Optimize/fix searching objects by-attribute-value
This commit is contained in:
parent
23767f4205
commit
b5d148b00a
2 changed files with 21 additions and 26 deletions
|
|
@ -154,7 +154,7 @@ class ObjectDBManager(TypedObjectManager):
|
|||
|
||||
Args:
|
||||
attribute_name (str): Attribute key to search for.
|
||||
attribute_value (str): Attribute value to search for.
|
||||
attribute_value (any): Attribute value to search for. This can also be database objects.
|
||||
candidates (list, optional): Candidate objects to limit search to.
|
||||
typeclasses (list, optional): Python pats to restrict matches with.
|
||||
|
||||
|
|
@ -175,31 +175,16 @@ class ObjectDBManager(TypedObjectManager):
|
|||
)
|
||||
type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q()
|
||||
|
||||
# This doesn't work if attribute_value is an object. Workaround below
|
||||
|
||||
if isinstance(attribute_value, (str, int, float, bool)):
|
||||
return self.filter(
|
||||
results = (
|
||||
self
|
||||
.filter(
|
||||
cand_restriction
|
||||
& type_restriction
|
||||
& Q(db_attributes__db_key=attribute_name, db_attributes__db_value=attribute_value)
|
||||
).order_by("id")
|
||||
else:
|
||||
# We must loop for safety since the referenced lookup gives deepcopy error if attribute value is an object.
|
||||
global _ATTR
|
||||
if not _ATTR:
|
||||
from evennia.typeclasses.models import Attribute as _ATTR
|
||||
cands = list(
|
||||
self.filter(
|
||||
cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name)
|
||||
)
|
||||
)
|
||||
results = [
|
||||
attr.objectdb_set.all()
|
||||
for attr in _ATTR.objects.filter(
|
||||
objectdb__in=cands, db_value=attribute_value
|
||||
).order_by("id")
|
||||
]
|
||||
return chain(*results)
|
||||
& Q(db_attributes__db_key=attribute_name)
|
||||
& Q(db_attributes__db_value=attribute_value))
|
||||
.order_by("id")
|
||||
)
|
||||
return results
|
||||
|
||||
def get_objs_with_db_property(self, property_name, candidates=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Modified for Evennia by Griatch and the Evennia community.
|
|||
from ast import literal_eval
|
||||
from datetime import datetime
|
||||
|
||||
from copy import deepcopy
|
||||
from copy import deepcopy, Error as CopyError
|
||||
from base64 import b64encode, b64decode
|
||||
from zlib import compress, decompress
|
||||
|
||||
|
|
@ -44,6 +44,7 @@ from django.forms.widgets import Textarea
|
|||
|
||||
from pickle import loads, dumps
|
||||
from django.utils.encoding import force_str
|
||||
from evennia.utils.dbserialize import pack_dbobj
|
||||
|
||||
|
||||
DEFAULT_PROTOCOL = 4
|
||||
|
|
@ -92,7 +93,16 @@ def dbsafe_encode(value, compress_object=False, pickle_protocol=DEFAULT_PROTOCOL
|
|||
# The reason this is important is because we do all of our lookups as
|
||||
# simple string matches, thus the character streams must be the same
|
||||
# for the lookups to work properly. See tests.py for more information.
|
||||
value = dumps(deepcopy(value), protocol=pickle_protocol)
|
||||
try:
|
||||
value = deepcopy(value)
|
||||
except CopyError:
|
||||
# this can happen on a manager query where the search query string is a
|
||||
# database model.
|
||||
value = pack_dbobj(value)
|
||||
|
||||
value = dumps(value, protocol=pickle_protocol)
|
||||
|
||||
|
||||
if compress_object:
|
||||
value = compress(value)
|
||||
value = b64encode(value).decode() # decode bytes to str
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue