Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add projects to solr search [PT-188115817] #1353

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 44 additions & 1 deletion rails/app/controllers/api/v1/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ def search_results_data
results = []
@search.results.each do |type, values|
next if type == :all
results.push group_data(type.downcase, values)
if type == :project
results.push project_data(values)
else
results.push group_data(type.downcase, values)
end
end
results
end
Expand All @@ -63,6 +67,45 @@ def group_data(type, collection)
}
end

def project_data(collection)
projects = []
collection.each do |project|
tags = {}
tags['subject_areas'] = []
tags['grade_levels'] = []

tags.each do |key, value|
list = project.send(key)
list.each do |o|
tags[key].push o.name
end
end

project_data = {
id: project.id,
name: project.name,
subject_areas: tags['subject_areas'],
grade_levels: tags['grade_levels'],
}

projects.push project_data
end

{
type: "projects",
header: view_context.t("HomePage.SearchResults.Projects"),
projects: projects,
pagination: {
current_page: collection.current_page,
total_pages: collection.total_pages,
start_item: collection.offset + 1,
end_item: collection.offset + collection.length,
total_items: collection.total_entries,
per_page: collection.per_page
}
}
end

def search_filters_data
filters = {}
filters[:number_authored_resources] = @search.number_authored_resources
Expand Down
23 changes: 23 additions & 0 deletions rails/app/models/admin/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ def project_researchers
project_users.where(is_researcher:true).map { |ru| ru.user }
end

# this has to be set AFTER SearchableModel is included so that sunspot doesn't alias #solr_search to #search
searchable do
text :name
string :name

text :landing_page_content
text :project_card_description
text :landing_page_slug

boolean :public

time :updated_at
time :created_at

string :grade_levels, :multiple => true do
grade_level_list
end

string :subject_areas, :multiple => true do
subject_area_list
end
end

has_many :project_materials, dependent: :destroy
has_many :external_activities, through: :project_materials, source: :material, source_type: 'ExternalActivity'
has_many :interactives, through: :project_materials, source: :material, source_type: 'Interactive'
Expand Down
25 changes: 24 additions & 1 deletion rails/app/models/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Search
attr_accessor :no_sensors
attr_accessor :sensors
attr_accessor :project_ids
attr_accessor :search_projects

attr_accessor :available_subject_areas
attr_accessor :available_grade_level_groups
Expand Down Expand Up @@ -144,7 +145,8 @@ def initialize(opts={})
self.include_mine = opts[:include_mine] || false
self.include_official = opts[:include_official] || false
self.include_templates = opts[:include_templates] || false
self.show_archived = opts[:show_archived] || false
self.show_archived = opts[:show_archived] || false
self.search_projects = opts[:search_projects] || false

self.fetch_available_filter_options()

Expand Down Expand Up @@ -206,6 +208,27 @@ def search
self.hits[:all] = []
self.total_entries[:all] = 0

if self.search_projects
# need to use #solr_search instead of #search as the project model already has a non-solr search method
_results = Admin::Project.solr_search do |s|
s.fulltext(self.text)
s.with(:public, true)
search_by_grade_levels(s)
search_by_subject_areas(s)

s.order_by(:name)

# no pagination on project searches, all results are shown on the first page load
end

self.results[:all] += _results.results
self.hits[:all] += _results.hits
self.total_entries[:all] += _results.results.total_entries
self.results[:project] = _results.results
self.hits[:project] = _results.hits
self.total_entries[:project] = _results.results.total_entries
end

self.clean_material_types.each do |type|

_results = self.engine.search(self.searchable_models) do |s|
Expand Down
2 changes: 2 additions & 0 deletions rails/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ en:
in the upper left to search all resources or view curated Collections of
resources by clicking the Collections link above.
</p>
SearchResults:
Projects: Collections

search:
only_mine: Resources I authored
Expand Down
102 changes: 102 additions & 0 deletions rails/spec/models/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -648,5 +648,107 @@ def collection(factory, count=3, opts={})
end
end

context "for projects" do
# create projects
let(:foo_project) {
FactoryBot.create(:project, name: "Foo", landing_page_slug: "first-project", public: true,
landing_page_content: "The foo project has content about cats",
project_card_description: "This is the description about felines",
grade_level_list: ["1", "2"], subject_area_list: ["Math"]
)
}
let(:bar_project) {
FactoryBot.create(:project, name: "Bar", landing_page_slug: "second-project", public: true,
landing_page_content: "The bar project also has content about cats",
project_card_description: "This is also the description about felines",
grade_level_list: ["1", "3"], subject_area_list: ["Math", "Chemistry"]
)
}
let(:baz_project) {
FactoryBot.create(:project, name: "Baz", landing_page_slug: "third-project", public: false,
landing_page_content: "The baz project is private and should not show in search results",
project_card_description: "This is the description about private projects",
grade_level_list: ["1", "2"], subject_area_list: ["Math"]
)
}
let(:search_opts) { { :search_projects => true } }

before(:each) do
foo_project
bar_project
baz_project
Admin::Project.reindex
Sunspot.commit
end

describe "with no options" do
it "returns in alphabetical name order filtering out private projects" do
expect(subject.results[:project].length).to eq(2)
expect(subject.results[:project][0].public).to be(true)
expect(subject.results[:project][1].public).to be(true)

expect(subject.results[:project][0].id).to be(bar_project.id)
expect(subject.results[:project][1].id).to be(foo_project.id)
end
end

describe "by name" do
let(:search_opts) { {:search_projects => true, :search_term => "foo"} }

it "results in 1 result" do
expect(subject.results[:project].length).to eq(1)
expect(subject.results[:project][0].id).to be(foo_project.id)
end
end

describe "by landing page content" do
let(:search_opts) { {:search_projects => true, :search_term => "cats"} }

it "results in 2 results" do
expect(subject.results[:project].length).to eq(2)

expect(subject.results[:project][0].id).to be(bar_project.id)
expect(subject.results[:project][1].id).to be(foo_project.id)
end
end

describe "by project card description" do
let(:search_opts) { {:search_projects => true, :search_term => "felines"} }

it "results in 2 results" do
expect(subject.results[:project].length).to eq(2)

expect(subject.results[:project][0].id).to be(bar_project.id)
expect(subject.results[:project][1].id).to be(foo_project.id)
end
end

describe "by landing page slug" do
let(:search_opts) { {:search_projects => true, :search_term => "second"} }

it "results in 1 result" do
expect(subject.results[:project].length).to eq(1)
expect(subject.results[:project][0].id).to be(bar_project.id)
end
end

describe "by grade levels" do
let(:search_opts) { {:search_projects => true, :grade_level_groups => ["3-4"]} }

it "results in 1 results" do
expect(subject.results[:project].length).to eq(1)
expect(subject.results[:project][0].id).to be(bar_project.id)
end
end

describe "by subject areas" do
let(:search_opts) { {:search_projects => true, :subject_areas => ["Chemistry"]} }

it "results in 1 results" do
expect(subject.results[:project].length).to eq(1)
expect(subject.results[:project][0].id).to be(bar_project.id)
end
end
end
end
end
Loading