From 35f540b26a87a875543d8d599c81334e539d5329 Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Mon, 5 Dec 2022 12:48:21 +0300 Subject: [PATCH] search-messages --- base/redis.py | 2 ++ resolvers/inbox/load.py | 43 +---------------------------------- resolvers/inbox/search.py | 48 ++++++++++++++++++++++++++++++++++++++- schema.graphql | 1 + 4 files changed, 51 insertions(+), 43 deletions(-) diff --git a/base/redis.py b/base/redis.py index ccc3758a..e1a4b903 100644 --- a/base/redis.py +++ b/base/redis.py @@ -31,9 +31,11 @@ class RedisCache: pass async def lrange(self, key, start, stop): + print(f"[redis] LRANGE {key} {start} {stop}") return await self._instance.lrange(key, start, stop) async def mget(self, key, *keys): + print(f"[redis] MGET {key} {keys}") return await self._instance.mget(key, *keys) diff --git a/resolvers/inbox/load.py b/resolvers/inbox/load.py index a6cf46bf..4fce0f94 100644 --- a/resolvers/inbox/load.py +++ b/resolvers/inbox/load.py @@ -76,36 +76,6 @@ async def load_chats(_, info, limit: int = 50, offset: int = 0): } -async def search_user_chats(by, messages, user_id: int, limit, offset): - cids = set([]) - by_author = by.get('author') - body_like = by.get('body') - cids.union(set(await redis.execute("SMEMBERS", "chats_by_user/" + str(user_id)))) - # messages_by_chat = [] - if by_author: - # all author's messages - cids.union(set(await redis.execute("SMEMBERS", f"chats_by_user/{by_author}"))) - # author's messages in filtered chat - messages.union(set(filter(lambda m: m["author"] == by_author, list(messages)))) - for c in cids: - c = c.decode('utf-8') - # messages_by_chat = await load_messages(c, limit, offset) - - if body_like: - # search in all messages in all user's chats - for c in cids: - # FIXME: use redis scan here - c = c.decode('utf-8') - mmm = set(await load_messages(c, limit, offset)) - for m in mmm: - if body_like in m["body"]: - messages.add(m) - else: - # search in chat's messages - messages.union(set(filter(lambda m: body_like in m["body"], list(messages)))) - return messages - - @query.field("loadMessagesBy") @login_required async def load_messages_by(_, info, by, limit: int = 10, offset: int = 0): @@ -129,18 +99,6 @@ async def load_messages_by(_, info, by, limit: int = 10, offset: int = 0): } # everyone's messages in filtered chat messages = await load_messages(by_chat, limit, offset) - - # if len(messages) == 0: - # messages.union(set(await search_user_chats(by, messages, auth.user_id, limit, offset))) - - # days = by.get("days") - # if days: - # messages.union(set(filter( - # list(messages), - # key=lambda m: ( - # datetime.now(tz=timezone.utc) - int(m["createdAt"]) < timedelta(days=by["days"]) - # ) - # ))) return { "messages": sorted( list(messages), @@ -161,6 +119,7 @@ async def load_recipients(_, info, limit=50, offset=0): try: chat_users += await followed_authors(auth.user_id) + print("[resolvers.inbox] ") limit = limit - len(chat_users) except Exception: pass diff --git a/resolvers/inbox/search.py b/resolvers/inbox/search.py index 20269e59..1ca340e5 100644 --- a/resolvers/inbox/search.py +++ b/resolvers/inbox/search.py @@ -1,11 +1,12 @@ import json - +from datetime import datetime, timezone, timedelta from auth.authenticate import login_required from auth.credentials import AuthCredentials from base.redis import redis from base.resolvers import query from base.orm import local_session from orm.user import AuthorFollower, User +from resolvers.inbox.load import load_messages @query.field("searchRecipients") @@ -47,3 +48,48 @@ async def search_recipients(_, info, query: str, limit: int = 50, offset: int = "members": list(result), "error": None } + + +@query.field("searchMessages") +@login_required +async def search_user_chats(by, messages, user_id: int, limit, offset): + cids = set([]) + cids.union(set(await redis.execute("SMEMBERS", "chats_by_user/" + str(user_id)))) + messages = [] + + by_author = by.get('author') + if by_author: + # all author's messages + cids.union(set(await redis.execute("SMEMBERS", f"chats_by_user/{by_author}"))) + # author's messages in filtered chat + messages.union(set(filter(lambda m: m["author"] == by_author, list(messages)))) + for c in cids: + c = c.decode('utf-8') + messages = await load_messages(c, limit, offset) + + body_like = by.get('body') + if body_like: + # search in all messages in all user's chats + for c in cids: + # FIXME: use redis scan here + c = c.decode('utf-8') + mmm = await load_messages(c, limit, offset) + for m in mmm: + if body_like in m["body"]: + messages.add(m) + else: + # search in chat's messages + messages.extend(filter(lambda m: body_like in m["body"], list(messages))) + + days = by.get("days") + if days: + messages.extend(filter( + list(messages), + key=lambda m: ( + datetime.now(tz=timezone.utc) - int(m["createdAt"]) < timedelta(days=by["days"]) + ) + )) + return { + "messages": messages, + "error": None + } diff --git a/schema.graphql b/schema.graphql index 647c9774..09cb934d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -270,6 +270,7 @@ type Query { loadMessagesBy(by: MessagesBy!, limit: Int, offset: Int): Result! loadRecipients(limit: Int, offset: Int): Result! searchRecipients(query: String!, limit: Int, offset: Int): Result! + searchMessages(by: MessagesBy!, limit: Int, offset: Int): Result! # auth isEmailUsed(email: String!): Boolean!