Last active
May 28, 2024 15:00
-
-
Save izelnakri/b9d569dda9d873222a3d077bd5cd4461 to your computer and use it in GitHub Desktop.
ecto/elixir search functionality
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SELECT company, | |
# GREATEST(similarity(company.sourced_name, 'search term'), similarity(company.local_name, 'search term'), similarity(company.name, 'search term')) AS rank | |
# FROM "companies" company | |
# WHERE (similarity(company.sourced_name, 'search term') > 0.1::float) OR | |
# (similarity(company.local_name, 'search term') > 0.1::float) OR | |
# (similarity(company.name, 'search term') > 0.1::float) | |
# ORDER BY rank DESC | |
# LIMIT 5; | |
defmodule Company do | |
use Application.Web, :model | |
# relationships: industry | |
schema "companies" do | |
field :sourced_name, :string | |
field :local_name, :string | |
field :name, :string | |
# other fields | |
end | |
def search(search_term) do | |
from( | |
company in Company, # normally these even have joins | |
select: %{ | |
company: company, | |
rank: fragment("GREATEST(similarity(?, ?), similarity(?, ?), similarity(?, ?)) AS rank", | |
company.local_name, ^search_term, company.sourced_name, ^search_term, company.name, ^search_term | |
), | |
}, | |
where: fragment("similarity(?, ?)", company.sourced_name, ^search_term) > 0.1 or | |
fragment("similarity(?, ?)", company.name, ^search_term) > 0.1 or | |
fragment("similarity(?, ?)", company.local_name, ^search_term) > 0.1, | |
order_by: fragment("rank DESC"), | |
limit: 5 | |
) | |
end | |
end | |
defmodule Controller do | |
use Web, :controller | |
import BaseSerializer | |
def search(conn, %{"query" => search_input}) do | |
companies_results = Company.search(search_input) |> Repo.all | |
# other two table searchs | |
results = complex_elixir_manipulation_stuff(companies_results ++ other_searches) | |
# data manipulation here to sort the order, merge some objects in two highly relational tables, | |
# prepare the data for ember. | |
json conn, %{results: results} | |
# the entire request takes like ~20-60ms locally, with all the things above | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// not very well written/simple concept for turning the search results to Ember Data Objects | |
// also useful for search-and-associate type of input fields. | |
import fetch from 'ember-network/fetch'; | |
import Ember from 'ember'; | |
import config from 'frontend/config/environment'; | |
const { Component, computed, inject } = Ember; | |
export default Component.extend({ | |
store: inject.service(), | |
keyUp() { | |
let query = $(event.target).val(); | |
if (this.get('searchPath') && query.length > 0) { | |
fetch(config.apiHost + `/${this.get('searchPath')}?search=${query}`).then((response) => { | |
return response.json(); | |
}).then((json) => { | |
var array = []; | |
json.results.forEach((result) => { | |
if (result.company) { | |
this.get('store').pushPayload({ company: result.company }); | |
array.push(this.get('store').peekRecord('company', result.company.id)); | |
} else if (result.person) { | |
this.get('store').pushPayload({ person: result.person }); | |
array.push(this.get('store').peekRecord('person', result.person.id)); | |
} | |
}); | |
this.set('results', Ember.A(array)); | |
}); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment