Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
552c0bc7
Commit
552c0bc7
authored
May 01, 2015
by
Martyn James
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move location identifying strings into index
parent
bd1e7a41
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
95 additions
and
135 deletions
+95
-135
cms/djangoapps/contentstore/courseware_index.py
+35
-0
cms/djangoapps/contentstore/tests/test_courseware_index.py
+59
-3
lms/lib/courseware_search/lms_result_processor.py
+0
-47
lms/lib/courseware_search/test/test_lms_result_processor.py
+1
-85
No files found.
cms/djangoapps/contentstore/courseware_index.py
View file @
552c0bc7
...
...
@@ -190,6 +190,7 @@ class SearchIndexerBase(object):
item_index
[
'id'
]
=
item_id
if
item
.
start
:
item_index
[
'start_date'
]
=
item
.
start
item_index
.
update
(
cls
.
supplemental_fields
(
item
))
searcher
.
index
(
cls
.
DOCUMENT_TYPE
,
item_index
)
indexed_count
[
"count"
]
+=
1
...
...
@@ -271,6 +272,14 @@ class SearchIndexerBase(object):
"""
pass
@classmethod
def
supplemental_fields
(
cls
,
item
):
# pylint: disable=unused-argument
"""
Any supplemental fields that get added to the index for the specified
item. Base implementation returns an empty dictionary
"""
return
{}
class
CoursewareSearchIndexer
(
SearchIndexerBase
):
"""
...
...
@@ -285,6 +294,8 @@ class CoursewareSearchIndexer(SearchIndexerBase):
'category'
:
'courseware_index'
}
UNNAMED_MODULE_NAME
=
_
(
"(Unnamed)"
)
@classmethod
def
normalize_structure_key
(
cls
,
structure_key
):
""" Normalizes structure key for use in indexing """
...
...
@@ -314,6 +325,30 @@ class CoursewareSearchIndexer(SearchIndexerBase):
"""
CourseAboutSearchIndexer
.
index_about_information
(
modulestore
,
structure
)
@classmethod
def
supplemental_fields
(
cls
,
item
):
"""
Add location path to the item object
Once we've established the path of names, the first name is the course
name, and the next 3 names are the navigable path within the edx
application. Notice that we stop at that level because a full path to
deep children would be confusing.
"""
location_path
=
[]
parent
=
item
while
parent
is
not
None
:
path_component_name
=
parent
.
display_name
if
not
path_component_name
:
path_component_name
=
cls
.
UNNAMED_MODULE_NAME
location_path
.
append
(
path_component_name
)
parent
=
parent
.
get_parent
()
location_path
.
reverse
()
return
{
"course_name"
:
location_path
[
0
],
"location"
:
location_path
[
1
:
4
]
}
class
LibrarySearchIndexer
(
SearchIndexerBase
):
"""
...
...
cms/djangoapps/contentstore/tests/test_courseware_index.py
View file @
552c0bc7
...
...
@@ -145,10 +145,10 @@ class MixedWithOptionsTestCase(MixedSplitTestCase):
""" Returns field_dictionary for default search """
return
{}
def
search
(
self
,
field_dictionary
=
None
):
def
search
(
self
,
field_dictionary
=
None
,
query_string
=
None
):
""" Performs index search according to passed parameters """
fields
=
field_dictionary
if
field_dictionary
else
self
.
_get_default_search
()
return
self
.
searcher
.
search
(
field_dictionary
=
fields
,
doc_type
=
self
.
DOCUMENT_TYPE
)
return
self
.
searcher
.
search
(
query_string
=
query_string
,
field_dictionary
=
fields
,
doc_type
=
self
.
DOCUMENT_TYPE
)
def
_perform_test_using_store
(
self
,
store_type
,
test_to_perform
):
""" Helper method to run a test function that uses a specific store """
...
...
@@ -220,7 +220,11 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
"""
Set up the for the course outline tests.
"""
self
.
course
=
CourseFactory
.
create
(
modulestore
=
store
,
start
=
datetime
(
2015
,
3
,
1
,
tzinfo
=
UTC
))
self
.
course
=
CourseFactory
.
create
(
modulestore
=
store
,
start
=
datetime
(
2015
,
3
,
1
,
tzinfo
=
UTC
),
display_name
=
"Search Index Test Course"
)
self
.
chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
course
.
location
,
...
...
@@ -485,6 +489,50 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
self
.
assertIn
(
CourseMode
.
HONOR
,
response
[
"results"
][
0
][
"data"
][
"modes"
])
self
.
assertIn
(
CourseMode
.
VERIFIED
,
response
[
"results"
][
0
][
"data"
][
"modes"
])
def
_test_course_location_info
(
self
,
store
):
""" Test that course location information is added to index """
self
.
publish_item
(
store
,
self
.
vertical
.
location
)
self
.
reindex_course
(
store
)
response
=
self
.
search
(
query_string
=
"Html Content"
)
self
.
assertEqual
(
response
[
"total"
],
1
)
result
=
response
[
"results"
][
0
][
"data"
]
self
.
assertEqual
(
result
[
"course_name"
],
"Search Index Test Course"
)
self
.
assertEqual
(
result
[
"location"
],
[
"Week 1"
,
"Lesson 1"
,
"Subsection 1"
])
def
_test_course_location_null
(
self
,
store
):
""" Test that course location information is added to index """
sequential2
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
category
=
'sequential'
,
display_name
=
None
,
modulestore
=
store
,
publish_item
=
True
,
start
=
datetime
(
2015
,
3
,
1
,
tzinfo
=
UTC
),
)
# add a new vertical
vertical2
=
ItemFactory
.
create
(
parent_location
=
sequential2
.
location
,
category
=
'vertical'
,
display_name
=
'Subsection 2'
,
modulestore
=
store
,
publish_item
=
True
,
)
ItemFactory
.
create
(
parent_location
=
vertical2
.
location
,
category
=
"html"
,
display_name
=
"Find Me"
,
publish_item
=
True
,
modulestore
=
store
,
)
self
.
reindex_course
(
store
)
response
=
self
.
search
(
query_string
=
"Find Me"
)
self
.
assertEqual
(
response
[
"total"
],
1
)
result
=
response
[
"results"
][
0
][
"data"
]
self
.
assertEqual
(
result
[
"course_name"
],
"Search Index Test Course"
)
self
.
assertEqual
(
result
[
"location"
],
[
"Week 1"
,
CoursewareSearchIndexer
.
UNNAMED_MODULE_NAME
,
"Subsection 2"
])
@patch
(
'django.conf.settings.SEARCH_ENGINE'
,
'search.tests.utils.ErroringIndexEngine'
)
def
_test_exception
(
self
,
store
):
""" Test that exception within indexing yields a SearchIndexingError """
...
...
@@ -536,6 +584,14 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
def
test_course_about_mode_index
(
self
,
store_type
):
self
.
_perform_test_using_store
(
store_type
,
self
.
_test_course_about_mode_index
)
@ddt.data
(
*
WORKS_WITH_STORES
)
def
test_course_location_info
(
self
,
store_type
):
self
.
_perform_test_using_store
(
store_type
,
self
.
_test_course_location_info
)
@ddt.data
(
*
WORKS_WITH_STORES
)
def
test_course_location_null
(
self
,
store_type
):
self
.
_perform_test_using_store
(
store_type
,
self
.
_test_course_location_null
)
@patch
(
'django.conf.settings.SEARCH_ENGINE'
,
'search.tests.utils.ForceRefreshElasticSearchEngine'
)
@ddt.ddt
...
...
lms/lib/courseware_search/lms_result_processor.py
View file @
552c0bc7
...
...
@@ -13,8 +13,6 @@ from xmodule.modulestore.search import path_to_location, navigation_index
from
courseware.access
import
has_access
UNNAMED_MODULE_NAME
=
_
(
"(Unnamed)"
)
class
LmsSearchResultProcessor
(
SearchResultProcessor
):
...
...
@@ -62,51 +60,6 @@ class LmsSearchResultProcessor(SearchResultProcessor):
kwargs
=
{
"course_id"
:
self
.
_results_fields
[
"course"
],
"location"
:
self
.
_results_fields
[
"id"
]}
)
@property
def
course_name
(
self
):
"""
Display the course name when searching multiple courses - retain result for subsequent uses
"""
if
self
.
_course_name
is
None
:
course
=
self
.
get_module_store
()
.
get_course
(
self
.
get_course_key
())
self
.
_course_name
=
course
.
display_name_with_default
return
self
.
_course_name
@property
def
location
(
self
):
"""
Blend "location" property into the resultset, so that the path to the found component can be shown within the UI
"""
# TODO: update whern changes to "cohorted-courseware" branch are merged in
(
course_key
,
chapter
,
section
,
position
)
=
path_to_location
(
self
.
get_module_store
(),
self
.
get_usage_key
())
def
get_display_name
(
item_key
):
""" gets display name from object's key """
item
=
self
.
get_item
(
item_key
)
display_name
=
getattr
(
item
,
"display_name"
,
None
)
return
display_name
if
display_name
else
UNNAMED_MODULE_NAME
def
get_position_name
(
section
,
position
):
""" helper to fetch name corresponding to the position therein """
if
position
:
section_item
=
self
.
get_item
(
course_key
.
make_usage_key
(
"sequential"
,
section
))
if
section_item
.
has_children
and
len
(
section_item
.
children
)
>=
position
:
return
get_display_name
(
section_item
.
children
[
position
-
1
])
return
None
location_description
=
[]
if
chapter
:
location_description
.
append
(
get_display_name
(
course_key
.
make_usage_key
(
"chapter"
,
chapter
)))
if
section
:
location_description
.
append
(
get_display_name
(
course_key
.
make_usage_key
(
"sequential"
,
section
)))
if
position
:
# We're only wanting to show the first vertical, so we use the
# navigation_index function to display the same location to which one
# would be sent if navigating
location_description
.
append
(
get_position_name
(
section
,
navigation_index
(
position
)))
return
location_description
def
should_remove
(
self
,
user
):
""" Test to see if this result should be removed due to access restriction """
return
not
has_access
(
...
...
lms/lib/courseware_search/test/test_lms_result_processor.py
View file @
552c0bc7
...
...
@@ -6,7 +6,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from
courseware.tests.factories
import
UserFactory
from
lms.lib.courseware_search.lms_result_processor
import
LmsSearchResultProcessor
,
UNNAMED_MODULE_NAME
from
lms.lib.courseware_search.lms_result_processor
import
LmsSearchResultProcessor
class
LmsSearchResultProcessorTestCase
(
ModuleStoreTestCase
):
...
...
@@ -85,71 +85,6 @@ class LmsSearchResultProcessorTestCase(ModuleStoreTestCase):
self
.
assertEqual
(
srp
.
url
,
"/courses/{}/jump_to/{}"
.
format
(
unicode
(
self
.
course
.
id
),
unicode
(
self
.
html
.
scope_ids
.
usage_id
)))
def
test_course_name_parameter
(
self
):
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
html
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is the html text"
}
},
"test"
)
self
.
assertEqual
(
srp
.
course_name
,
self
.
course
.
display_name
)
def
test_location_parameter
(
self
):
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
html
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is html test text"
}
},
"test"
)
self
.
assertEqual
(
len
(
srp
.
location
),
3
)
self
.
assertEqual
(
srp
.
location
[
0
],
'Test Section'
)
self
.
assertEqual
(
srp
.
location
[
1
],
'Test Subsection'
)
self
.
assertEqual
(
srp
.
location
[
2
],
'Test Unit'
)
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
vertical
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is html test text"
}
},
"test"
)
self
.
assertEqual
(
len
(
srp
.
location
),
3
)
self
.
assertEqual
(
srp
.
location
[
0
],
'Test Section'
)
self
.
assertEqual
(
srp
.
location
[
1
],
'Test Subsection'
)
self
.
assertEqual
(
srp
.
location
[
2
],
'Test Unit'
)
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
subsection
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is html test text"
}
},
"test"
)
self
.
assertEqual
(
len
(
srp
.
location
),
2
)
self
.
assertEqual
(
srp
.
location
[
0
],
'Test Section'
)
self
.
assertEqual
(
srp
.
location
[
1
],
'Test Subsection'
)
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
section
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is html test text"
}
},
"test"
)
self
.
assertEqual
(
len
(
srp
.
location
),
1
)
self
.
assertEqual
(
srp
.
location
[
0
],
'Test Section'
)
def
test_should_remove
(
self
):
"""
Tests that "visible_to_staff_only" overrides start date.
...
...
@@ -164,22 +99,3 @@ class LmsSearchResultProcessorTestCase(ModuleStoreTestCase):
)
self
.
assertEqual
(
srp
.
should_remove
(
self
.
global_staff
),
False
)
def
test_missing_display_name
(
self
):
"""
Tests that we get the correct name to include when there is an empty or null display name
"""
srp
=
LmsSearchResultProcessor
(
{
"course"
:
unicode
(
self
.
course
.
id
),
"id"
:
unicode
(
self
.
ghost_html
.
scope_ids
.
usage_id
),
"content"
:
{
"text"
:
"This is html test text"
}
},
"test"
)
location
=
srp
.
location
self
.
assertEqual
(
len
(
location
),
3
)
self
.
assertEqual
(
location
[
0
],
self
.
section
.
display_name
)
self
.
assertEqual
(
location
[
1
],
UNNAMED_MODULE_NAME
)
self
.
assertEqual
(
location
[
2
],
UNNAMED_MODULE_NAME
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment