Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7924acc
removed discovery legacy search
ihorsokhanexoft Apr 7, 2026
35dca89
removed /search/ legacy route
ihorsokhanexoft Apr 7, 2026
7a45982
remove api/v1/user/search/ legacy route
ihorsokhanexoft Apr 7, 2026
f3e63d4
removed api/v1/search/node/ legacy route
ihorsokhanexoft Apr 7, 2026
f6abdb4
removed api/v1/share/search/ legacy route
ihorsokhanexoft Apr 7, 2026
be6e090
removed api/v1/search/projects/ legacy route
ihorsokhanexoft Apr 8, 2026
a8c11bd
removed api/v1/search/ and api/v1/search/<type>/ legacy routes
ihorsokhanexoft Apr 8, 2026
d6d3357
removed unused website/search process_project_search_results function
ihorsokhanexoft Apr 8, 2026
c8a2724
removed api/v2/search/ endpoint
ihorsokhanexoft Apr 8, 2026
b3788ad
removed api/v2/search/components/ endpoint
ihorsokhanexoft Apr 8, 2026
408b47e
removed api/v2/search/files/ endpoint
ihorsokhanexoft Apr 8, 2026
d3fbfbd
removed api/v2/search/projects/ endpoint
ihorsokhanexoft Apr 8, 2026
44a3c8b
removed api/v2/search/registrations/ endpoint
ihorsokhanexoft Apr 8, 2026
2f763bc
removed api/v2/search/users/ endpoint
ihorsokhanexoft Apr 8, 2026
0f7f096
removed api/v2/search/institutions/ endpoint
ihorsokhanexoft Apr 8, 2026
0e8f7ea
removed api/v2/search/collections/ endpoint, scopes and its dependencies
ihorsokhanexoft Apr 8, 2026
5c9e978
removed api/v2/search/ base route
ihorsokhanexoft Apr 9, 2026
8a9243a
removed test related to legacy /explore/ route
ihorsokhanexoft Apr 9, 2026
7caebb5
Merge branch 'feature/es2-consolidation' into feature/ENG-9820
ihorsokhanexoft May 13, 2026
8cbbe7d
Merge branch 'feature/es2-consolidation' into feature/ENG-9820
ihorsokhanexoft May 13, 2026
977d0b1
removed missed test case
ihorsokhanexoft May 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions api/base/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,26 +114,6 @@ def remove_invalid_fields(self, queryset, fields, view, request):
return valid_fields


class ElasticOSFOrderingFilter(OSFOrderingFilter):
""" This is too enable sorting for ES endpoints that use ES results instead of a typical queryset"""
def filter_queryset(self, request, queryset, view):
sorted_list = queryset.copy()
sort = request.query_params.get('sort')
reverse = False
if sort:
if sort.startswith('-'):
sort = sort.lstrip('-')
reverse = True

try:
source = view.get_serializer_class()._declared_fields[sort].source
sorted_list['results'] = sorted(queryset['results'], key=lambda item: item['_source'][source], reverse=reverse)
except KeyError:
pass

return sorted_list


class FilterMixin:
""" View mixin with helper functions for filtering. """

Expand Down
179 changes: 0 additions & 179 deletions api/base/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
)
from api.base.serializers import is_anonymized
from api.base.settings import MAX_PAGE_SIZE, MAX_SIZE_OF_ES_QUERY
from api.base.utils import absolute_reverse

from osf.models import AbstractNode, Comment, Preprint, Guid, DraftRegistration
from website.search.elastic_search import DOC_TYPE_TO_MODEL


class JSONAPIPagination(pagination.PageNumberPagination):
Expand Down Expand Up @@ -263,180 +261,3 @@ class DraftRegistrationContributorPagination(NodeContributorPagination):
def get_resource(self, kwargs):
resource_id = kwargs.get('draft_id')
return DraftRegistration.load(resource_id)


class SearchPaginator(DjangoPaginator):

def __init__(self, object_list, per_page):
super().__init__(object_list, per_page)

def search_type_to_model(self, obj_id, obj_type):
model = DOC_TYPE_TO_MODEL[obj_type]
return model.load(obj_id)

def _get_count(self):
self._count = self.object_list['aggs']['total']
return self._count
count = property(_get_count)

def page(self, number):
number = self.validate_number(number)
results = self.object_list['results']
items = [
self.search_type_to_model(result.get('_id'), result.get('_type'))
for result in results
]
return self._get_page(items, number, self)


class SearchModelPaginator(SearchPaginator):

def __init__(self, object_list, per_page, model):
super().__init__(object_list, per_page)
self.model = model

def page(self, number):
number = self.validate_number(number)
results = self.object_list['results']
items = [
self.model.load(result.get('_id'))
for result in results
]
return self._get_page(items, number, self)


class SearchPagination(JSONAPIPagination):

def __init__(self):
super().__init__()
self.paginator = None

def paginate_queryset(self, queryset, request, view=None):
page_size = self.get_page_size(request)
if not page_size:
return None

# Pagination requires an order by clause, especially when using Postgres.
# see: https://docs.djangoproject.com/en/1.10/topics/pagination/#required-arguments
if isinstance(queryset, QuerySet) and not queryset.ordered:
queryset = queryset.order_by(queryset.model._meta.pk.name)

self.paginator = SearchPaginator(queryset, page_size)
model = getattr(request.parser_context['view'], 'model_class', None)
if model:
self.paginator = SearchModelPaginator(queryset, page_size, model)

page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = self.paginator.num_pages

try:
self.page = self.paginator.page(page_number)
except InvalidPage as exc:
msg = self.invalid_page_message.format(
page_number=page_number, message=str(exc),
)
raise NotFound(msg)

if self.paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True

self.request = request
return list(self.page)

def get_search_field_url(self, field, query):
view_name = f'search:search-{field}'
return absolute_reverse(
view_name,
query_kwargs={
'q': query,
},
kwargs={
'version': self.request.parser_context['kwargs']['version'],
},
)

def get_search_field_total(self, field):
return self.paginator.object_list['counts'].get(field, 0)

def get_search_field(self, field, query):
return OrderedDict([
(
'related', OrderedDict([
('href', self.get_search_field_url(field, query)),
(
'meta', OrderedDict([
('total', self.get_search_field_total(field)),
]),
),
]),
),
])

def get_response_dict(self, data, url):
if isinstance(self.paginator, SearchModelPaginator):
return super().get_response_dict(data, url)
else:
query = self.request.query_params.get('q', '*')
return OrderedDict([
('data', data),
(
'search_fields', OrderedDict([
('files', self.get_search_field('file', query)),
('projects', self.get_search_field('project', query)),
('components', self.get_search_field('component', query)),
('registrations', self.get_search_field('registration', query)),
('users', self.get_search_field('user', query)),
('institutions', self.get_search_field('institution', query)),
]),
),
(
'meta', OrderedDict([
('total', self.page.paginator.count),
('per_page', self.page.paginator.per_page),
]),
),
(
'links', OrderedDict([
('self', self.get_self_real_link(url)),
('first', self.get_first_real_link(url)),
('last', self.get_last_real_link(url)),
('prev', self.get_previous_real_link(url)),
('next', self.get_next_real_link(url)),
]),
),
])

def get_response_dict_deprecated(self, data, url):
if isinstance(self.paginator, SearchModelPaginator):
return super().get_response_dict_deprecated(data, url)
else:
query = self.request.query_params.get('q', '*')
return OrderedDict([
('data', data),
(
'search_fields', OrderedDict([
('files', self.get_search_field('file', query)),
('projects', self.get_search_field('project', query)),
('components', self.get_search_field('component', query)),
('registrations', self.get_search_field('registration', query)),
('users', self.get_search_field('user', query)),
('institutions', self.get_search_field('institution', query)),
]),
),
(
'links', OrderedDict([
('first', self.get_first_real_link(url)),
('last', self.get_last_real_link(url)),
('prev', self.get_previous_real_link(url)),
('next', self.get_next_real_link(url)),
(
'meta', OrderedDict([
('total', self.page.paginator.count),
('per_page', self.page.paginator.per_page),
]),
),
]),
),
])
50 changes: 0 additions & 50 deletions api/base/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import time
import collections
from jsonschema import validate, ValidationError, Draft7Validator
from django.core.exceptions import ImproperlyConfigured
from rest_framework.parsers import JSONParser
from rest_framework.exceptions import ParseError, NotAuthenticated

Expand Down Expand Up @@ -307,52 +306,3 @@ def parse(self, stream, media_type=None, parser_context=None):
raise JSONAPIException(detail='Signature has expired')

return payload

class SearchParser(JSONAPIParser):

def parse(self, stream, media_type=None, parser_context=None):
try:
view = parser_context['view']
except KeyError:
raise ImproperlyConfigured('SearchParser requires "view" context.')
data = super().parse(stream, media_type=media_type, parser_context=parser_context)
if not data:
raise JSONAPIException(detail='Invalid Payload')

res = {
'query': {
'bool': {},
},
}

sort = parser_context['request'].query_params.get('sort')
if sort:
res['sort'] = [{
sort.lstrip('-'): {
'order': 'desc' if sort.startswith('-') else 'asc',
},
}]

try:
q = data.pop('q')
except KeyError:
pass
else:
res['query']['bool'].update({
'must': {
'query_string': {
'query': q,
'fields': view.search_fields,
},
},
})

if any(data.values()):
res['query']['bool'].update({'filter': []})
for key, val in data.items():
if val is not None:
if isinstance(val, list):
res['query']['bool']['filter'].append({'terms': {key: val}})
else:
res['query']['bool']['filter'].append({'term': {key: val}})
return res
1 change: 0 additions & 1 deletion api/base/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
re_path(r'^requests/', include(('api.requests.urls', 'requests'), namespace='requests')),
re_path(r'^resources/', include('api.resources.urls', namespace='resources')),
re_path(r'^scopes/', include('api.scopes.urls', namespace='scopes')),
re_path(r'^search/', include('api.search.urls', namespace='search')),
re_path(r'^sparse/', include('api.sparse.urls', namespace='sparse')),
re_path(r'^subjects/', include('api.subjects.urls', namespace='subjects')),
re_path(r'^subscriptions/', include('api.subscriptions.urls', namespace='subscriptions')),
Expand Down
Empty file removed api/search/__init__.py
Empty file.
8 changes: 0 additions & 8 deletions api/search/permissions.py

This file was deleted.

58 changes: 0 additions & 58 deletions api/search/serializers.py

This file was deleted.

19 changes: 0 additions & 19 deletions api/search/urls.py

This file was deleted.

Loading