У меня есть таблица в БД с почти 20 миллионами записей. Я хочу искать через регулярные выражения. Все было хорошо, когда количество записей было около 100 тысяч. Но сейчас это занимает довольно много времени, даже иногда это приводит к тайм-ауту. Нужно ли переходить на SQL базу данных, может быть postgresql
или что-то типа elasti c search. Как ожидается, записи в этой таблице увеличатся более чем на 20 миллиардов. Может есть способ повысить его эффективность, сохранив те же настройки, которые я использую djongo
для подключения django
к mongodb
, или мне нужно использовать любую другую базу данных для быстрого поиска.
Моя схема модели:
from djongo import models as model
class User(model.Model):
email = model.CharField(max_length=50, default='')
source = model.CharField(default='unknown',max_length=150)
username = model.CharField(max_length=150, default='')
hash = model.CharField(max_length=255, default='')
salt = model.CharField(max_length=255, default='')
ipaddress = model.CharField(max_length=50,default='')
lastipaddress = model.CharField(max_length=50,default='')
name = model.CharField(max_length=150, default='')
dateofbirth = model.CharField(max_length=100, default='')
phonenumber = model.CharField(max_length=100, default='')
firstname = model.CharField(max_length=150, default='')
lastname = model.CharField(max_length=150, default='')
address = model.CharField(max_length=255, default='')
objects = model.DjongoManager()
Этот метод вызывается, когда почтовый запрос отправляется на django
@api_view(['POST'])
@authentication_classes([authentication.TokenAuthentication])
@permission_classes([permissions.IsAdminUser])
def search(request):
if 'username' in request.data:
username = request.data['username']
if 'email' in request.data:
useremail = request.data['email']
if 'userid' in request.data:
userid = request.data['userid']
if 'query' in request.data:
query = request.data['query']
else:
return Response(status.HTTP_400_BAD_REQUEST)
obj = {}
obj['query'] = query
obj['type'] = type
obj['wildcard'] = wildcard
obj['regex'] = regex
if not (type in ['email', 'domain', 'username'] and wildcard == 'false' and regex == 'false'):
obj['request'] = request
final = []
print('wildcard', wildcard)
print('regex', regex)
print('type', type)
if wildcard == 'true' or regex == 'true':
with concurrent.futures.ThreadPoolExecutor() as executor:
t1 = executor.submit(getRecordsFromDB, obj)
final = t1.result()
return final
Вызывается описанным выше методом здесь, где выполняются запросы регулярных выражений
def getRecordsFromDB(obj):
max_limit = 10000
if obj['wildcard'] == "false" and obj['regex'] == "true":
print("yes regex thing")
if obj['type'] == 'domain':
obj['query'] = r'.+@{1}' + obj['query']
obj['type'] = 'email'
try:
pagination_class = LimitOffsetPagination
paginator = pagination_class()
queryset = User.objects.mongo_find({
obj['type']: {'$regex': obj['query']}
}).count()
if queryset > max_limit:
return Response(status.HTTP_507_INSUFFICIENT_STORAGE)
else:
queryset = User.objects.mongo_find({
obj['type']: {'$regex': obj['query']}
})
page = paginator.paginate_queryset(queryset, obj['request'])
serializer = UserSerializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
except Exception as err:
print(f'Other error occurred: {err}')
return Response(status.HTTP_422_UNPROCESSABLE_ENTITY)
elif obj['wildcard'] == "true" and obj['regex'] == "false":
print("yes wildcard thing")
#obj['query'] = obj['query'].replace('.', r'\.')
obj['query'] = re.escape(obj['query'])
obj['query'] = obj['query'].replace('\*', r'[a-zA-Z0-9-_.]*')
print('below is the respective regex for the given query')
print(obj['query'])
if obj['query'][0] != r'*' and obj['type'] != 'domain':
print('yes here where it should not be')
obj['query'] = r'^' + obj['query']
if len(obj['query']) > 1:
if obj['query'][-1] != r'*':
obj['query'] = obj['query'] + r'$'
print('final regex ', obj['query'])
if obj['type'] == 'domain':
obj['query'] = r'.+@{1}' + obj['query']
obj['type'] = 'email'
print('very final regex ', obj['query'])
try:
pagination_class = LimitOffsetPagination
paginator = pagination_class()
queryset = User.objects.mongo_find({
obj['type']: {'$regex': obj['query']}
}).count()
if queryset > max_limit:
return Response(status.HTTP_507_INSUFFICIENT_STORAGE)
else:
queryset = User.objects.mongo_find({
obj['type']: {'$regex': obj['query']}
})
page = paginator.paginate_queryset(queryset, obj['request'])
serializer = UserSerializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
except Exception as err:
print(f'Other error occurred: {err}')
return Response(status.HTTP_422_UNPROCESSABLE_ENTITY)
return records