私は以下のモデルでdjangoプロジェクトを進めています。逆の関係でAND検索
class User(models.Model):
pass
class Item(models.Model):
user = models.ForeignKey(User)
item_id = models.IntegerField()
約1,000万のアイテムと10万人のユーザーがあります。
私の目標は、永遠にかかるデフォルトの管理者の検索を無効にすることです。 は、指定したアイテムIDの「すべて」を所有する一致するすべてのユーザーを適切な時間枠で返します。
これは私の基準をよりよく説明するために使用する2つのテストです。
class TestSearch(TestCase):
def search(self, searchterm):
"""A tuple is returned with the first element as the queryset"""
return do_admin_search(User.objects.all())
def test_return_matching_users(self):
user = User.objects.create()
Item.objects.create(item_id=12345, user=user)
Item.objects.create(item_id=67890, user=user)
result = self.search('12345 67890')
assert_equal(1, result[0].count())
assert_equal(user, result[0][0])
def test_exclude_users_that_do_not_match_1(self):
user = User.objects.create()
Item.objects.create(item_id=12345, user=user)
result = self.search('12345 67890')
assert_false(result[0].exists())
def test_exclude_users_that_do_not_match_2(self):
user = User.objects.create()
result = self.search('12345 67890')
assert_false(result[0].exists())
次のスニペットは、annotate
を使用して50秒以上かかる最高の試みです。
def search_by_item_ids(queryset, item_ids):
params = {}
for i in item_ids:
cond = Case(When(item__item_id=i, then=True), output_field=BooleanField())
params['has_' + str(i)] = cond
queryset = queryset.annotate(**params)
params = {}
for i in item_ids:
params['has_' + str(i)] = True
queryset = queryset.filter(**params)
return queryset
スピードアップのためにできることはありますか?
残念ながら、私は、 'item__item__id__in'が私の場合にはうまくいかないため、idのいずれかを所有するすべてのユーザーではなく、指定したアイテムIDの' all 'を所有するすべてのユーザーを取得する必要があります。 – k8tems