Merge branch 'main' into suggestions-redis
This commit is contained in:
@ -8,27 +8,27 @@ from bookwyrm.redis_store import RedisStore, r
|
||||
|
||||
|
||||
class SuggestedUsers(RedisStore):
|
||||
""" suggested users for a user """
|
||||
"""suggested users for a user"""
|
||||
|
||||
max_length = 30
|
||||
|
||||
def get_rank(self, obj):
|
||||
""" get computed rank """
|
||||
"""get computed rank"""
|
||||
return obj.mutuals + (1.0 - (1.0 / (obj.shared_books + 1)))
|
||||
|
||||
def store_id(self, user): # pylint: disable=no-self-use
|
||||
""" the key used to store this user's recs """
|
||||
"""the key used to store this user's recs"""
|
||||
return "{:d}-suggestions".format(user.id)
|
||||
|
||||
def get_counts_from_rank(self, rank): # pylint: disable=no-self-use
|
||||
""" calculate mutuals count and shared books count from rank """
|
||||
"""calculate mutuals count and shared books count from rank"""
|
||||
return {
|
||||
"mutuals": math.floor(rank),
|
||||
"shared_books": int(1 / (-1 * (1 % rank - 1))) if rank else 0,
|
||||
}
|
||||
|
||||
def get_objects_for_store(self, store):
|
||||
""" a list of potential follows for a user """
|
||||
"""a list of potential follows for a user"""
|
||||
user = models.User.objects.get(id=store.split("-")[0])
|
||||
|
||||
return get_annotated_users(
|
||||
@ -43,13 +43,13 @@ class SuggestedUsers(RedisStore):
|
||||
return [self.store_id(u) for u in self.get_users_for_object(obj)]
|
||||
|
||||
def get_users_for_object(self, obj): # pylint: disable=no-self-use
|
||||
""" given a user, who might want to follow them """
|
||||
"""given a user, who might want to follow them"""
|
||||
return models.User.objects.filter(
|
||||
local=True,
|
||||
).exclude(following=obj)
|
||||
|
||||
def rerank_obj(self, obj, update_only=True):
|
||||
""" update all the instances of this user with new ranks """
|
||||
"""update all the instances of this user with new ranks"""
|
||||
pipeline = r.pipeline()
|
||||
for store_user in self.get_users_for_object(obj):
|
||||
annotated_user = get_annotated_users(
|
||||
@ -60,16 +60,16 @@ class SuggestedUsers(RedisStore):
|
||||
pipeline.zadd(
|
||||
self.store_id(store_user),
|
||||
self.get_value(annotated_user),
|
||||
xx=update_only
|
||||
xx=update_only,
|
||||
)
|
||||
pipeline.execute()
|
||||
|
||||
def rerank_user_suggestions(self, user):
|
||||
""" update the ranks of the follows suggested to a user """
|
||||
"""update the ranks of the follows suggested to a user"""
|
||||
self.populate_store(self.store_id(user))
|
||||
|
||||
def get_suggestions(self, user):
|
||||
""" get suggestions """
|
||||
"""get suggestions"""
|
||||
values = self.get_store(self.store_id(user), withscores=True)
|
||||
results = []
|
||||
# annotate users with mutuals and shared book counts
|
||||
@ -83,7 +83,7 @@ class SuggestedUsers(RedisStore):
|
||||
|
||||
|
||||
def get_annotated_users(viewer, *args, **kwargs):
|
||||
""" Users, annotated with things they have in common """
|
||||
"""Users, annotated with things they have in common"""
|
||||
return (
|
||||
models.User.objects.filter(discoverable=True, is_active=True, *args, **kwargs)
|
||||
.exclude(Q(id__in=viewer.blocks.all()) | Q(blocks=viewer))
|
||||
@ -117,7 +117,7 @@ suggested_users = SuggestedUsers()
|
||||
@receiver(signals.post_save, sender=models.UserFollows)
|
||||
# pylint: disable=unused-argument
|
||||
def update_suggestions_on_follow(sender, instance, created, *args, **kwargs):
|
||||
""" remove a follow from the recs and update the ranks"""
|
||||
"""remove a follow from the recs and update the ranks"""
|
||||
if (
|
||||
not created
|
||||
or not instance.user_subject.local
|
||||
@ -134,7 +134,7 @@ def update_suggestions_on_follow(sender, instance, created, *args, **kwargs):
|
||||
@receiver(signals.post_delete, sender=models.ShelfBook)
|
||||
# pylint: disable=unused-argument
|
||||
def update_rank_on_shelving(sender, instance, *args, **kwargs):
|
||||
""" when a user shelves or unshelves a book, re-compute their rank """
|
||||
"""when a user shelves or unshelves a book, re-compute their rank"""
|
||||
if not instance.user.discoverable:
|
||||
return
|
||||
suggested_users.rerank_obj(instance.user)
|
||||
@ -145,7 +145,7 @@ def update_rank_on_shelving(sender, instance, *args, **kwargs):
|
||||
def add_or_remove_on_discoverability_change(
|
||||
sender, instance, created, raw, using, update_fields, **kwargs
|
||||
):
|
||||
""" make a user (un)discoverable """
|
||||
"""make a user (un)discoverable"""
|
||||
if created:
|
||||
suggested_users.rerank_user_suggestions(instance)
|
||||
|
||||
|
Reference in New Issue
Block a user