지난번에 했던 거를.. 완전 잘못 생각한 치명적 오류가 있어서 새로 알고리즘을 짰다. 새로 테이블 만들어서 foreign key로 연결할 필요도 없었다.
진짜 멍청하기 짝이 없다
삽질기록..
내가 하려는 것: 검색필터를 통해 이미 한번 걸러진 Nac의 데이터 중에, user를 기준으로 데이터 갯수가 많은 것부터 순서대로 5개의 user를 정렬
지난 번에 했던대로 Accessor
테이블을 연결하면, Accessor
에 저장되는 count
는 지금까지의 접근 전체 count이므로 날짜나 시간으로 검색을 했을 경우에는 원하는 결과가 나오지 않는다.
예를 들어 3월 접근 순위를 보고 싶어서 2020-03
을 검색하지만, 나오는 순위는 현재까지의 접근 전체를 기준으로 걸러진 것이라는 것.
진짜 너무 멍청해서 할 말이 없다....
왜 그 때는 그렇게 밖에 생각을 하지 못했는지 참 알 수 없다.
그래서 뚝딱 다시 짜봤다.
일단, 간단히 이야기 하면 날짜나 시간으로 검색을 했을 때, 해당 날짜로 걸러진 데이터들 중에서 user갯수가 많은 순으로 정렬해서 상위 5개를 뽑는 거다.
정렬이라 하면 order_by
를 떠올리게 되는데, user는 문자열이라 문자열을 order_by
로 정렬하면 갯수가 아니라, 문자의 순서로 정렬이 된다.
그래서 따로 user별로 데이터의 갯수를 세야 한다.
1) 검색 쿼리로 해당 날짜에 해당하는 데이터들을 뽑기
2) 뽑은 데이터들에 존재하는 user
목록을 중복없는 리스트로 만들기
3) 각각의 user
에 해당하는 데이터들의 갯수를 세서 user
와 매칭하기 (dictionary
사용)
4) user
에 매칭되는 갯수를 내림차순으로 정렬하기
5) 정렬된 dictionary
에서 key값인 user
의 맨 앞 5개 가져오기
# django views.py
from django.shortcuts import render, redirect
from .models import Nac
from django.db.models import Q
from django.db.models import Count
import operator
def nacSearch(request):
search = request.GET.get('search', '') # 검색 쿼리
if search:
nacList = Nac.objects.all().order_by('-id')
nacList_search = nacList.filter(Q(time__icontains=search) | Q(user_id__name__icontains=search) |
Q(ip__icontains=search) | Q(result__icontains=search) | Q(message__icontains=search)) # 검색 결과 데이터 필터링
nac_access_rank = {} # user별 데이터 갯수를 매칭하여 저장할 dictionary
nacList_user = nacList_search.values_list('user_id__name', flat=True).distinct() # 검색결과의 user 목록; 테이블 구조는 지난번과 같음.
for user in nacList_user:
nac_access_rank[user] = nacList_search.filter(user_id__name=user).count() # user을 key로, 해당 user의 데이터 갯수를 value로 가짐
nac_rank = sorted(nac_access_rank.items(), key=operator.itemgetter(1), reverse=True) # value값을 기준으로 내림차순 정렬
nac_rank = nac_rank[:5] #앞 5개 데이터만 가져옴
return render(request, 'nac_search.html', {'nac_rank':nac_rank})
else:
return redirect('/system/nac/')
...
<div class="summary__card">
<h4 class="summary__card_info">
🔍검색 결과 접근 top 5:
</br>
{% if nac_rank %}
{% for rank in nac_rank %}
{{forloop.counter}}위 <span class="search_result">{{rank.0}}</span><span>({{rank.1}}회)</span>
{% endfor %}
{% endif %}
</h4>
</div>
이렇게 하면
이렇게 2021-02
로 검색했을 때, 해당 기간 안에 접근한 사람만 순위로 뽑아낼 수 있다.
성공~