2016-09-16 4 views
0

나는 간단한 모델이 있습니다

schema "torrents" do 
    field :name, :string 
    field :magnet, :string 
    field :leechers, :integer 
    field :seeders, :integer 
    field :source, :string 
    field :filesize, :string 

    timestamps() 
end 

을 그리고 이름에 따라 검색 할. 관련 확장과 색인을 데이터베이스와 테이블에 추가했습니다.

def change do 
    create table(:torrents) do 
    add :name, :string 
    add :magnet, :text 
    add :leechers, :integer 
    add :seeders, :integer 
    add :source, :string 
    add :filesize, :string 

    timestamps() 
    end 

    execute "CREATE EXTENSION pg_trgm;" 
    execute "CREATE INDEX torrents_name_trgm_index ON torrents USING gin (name gin_trgm_ops);" 

    create index(:torrents, [:magnet], unique: true) 
end 

나는 검색어, 를 사용하여 검색하기 위해 노력하고있어하지만 난 항상 0이 결과 얻을.

def search(query, search_term) do 
    from(u in query, 
    where: fragment("? % ?", u.name, ^search_term), 
    order_by: fragment("similarity(?, ?) DESC", u.name, ^search_term)) 
end 

SELECT t0."id", t0."name", t0."magnet", t0."leechers", t0."seeders", t0."source", 
t0."filesize", t0."inserted_at", t0."updated_at" FROM "torrents" 
AS t0 WHERE (t0."name" % $1) ORDER BY similarity(t0."name", $2) DESC ["a", "a"] 

내 검색 기능에 문제가 있습니까?

+0

콘솔에 오류가 기록됩니까? PostgreSQL 문서에서'% '가'WHERE (t0. "name"% $ 1 ")에 무엇을 의미하는지 찾을 수 없습니다. – Dogbert

+0

@Dogbert 오류가 없으며 적절한 SQL 명령 출력 만 있습니다. 이 기사의 명령이 있습니다. http://blog.rokkincat.com/postgres-full-text-search-inecto/ –

+0

테이블에 어떤 레코드가 있습니까? 여러분의 질의는 이름에 'a'가 포함 된 모든 레코드와 일치하지는 않을 것이지만, 충분히 비슷한 이름을 가진 레코드와 일치합니다. 이름이 ""a "인 레코드를 만들고 동일한 쿼리를 실행하십시오. 또는''ab ''와''abc ''를 만들고''ab''를 검색하십시오. – Dogbert

답변

1

초기 추정치는 % 연산자를 사용하기 때문에 일치하는 최소 한도가 쿼리에 비해 너무 높다는 것입니다. 이 제한은 기본적으로 0.3 (문자열 'trigrams가 30 % 유사 함을 의미)으로 설정됩니다. 이 임계 값이 충족되지 않으면 결과가 리턴되지 않습니다.

문제가있는 경우이 임계 값은 몇 가지 방법으로 구성 할 수 있습니다. set_limit (docs here)을 사용하거나 쿼리 단위로 제한을 설정할 수 있습니다.

set_limit 옵션은 매번 연결될 때마다 설정해야하기 때문에 약간 번거로운 작업이 될 수 있습니다. Ecto (db_connection을 통해)에는 after_connect (docs here)에 대한 콜백 함수를 설정할 수있는 옵션이 있습니다. 난 당신이 하나를 얻을 수 있는지 확인하기 위해 0의 한계와 그 시도 것,

def search(query, search_term, limit = 0.3) do 
    from(u in query, 
    where: fragment("similarity(?, ?) > ?", u.name, ^search_term, ^limit), 
    order_by: fragment("similarity(?, ?) DESC", u.name, ^search_term)) 
end 

시작하려면

는 다음과 같이 WHERE 절에 similarity 기능을 사용할 수, 쿼리 당 제한을 변경하려면 결과.

+0

대신 함수 서명을 사용해야합니다 :'def search (query, search_term, limit \\ 0)'? –

+0

검색이 2 초 정도 걸리며 정상입니까? 훨씬 빨라야하지 않습니까? 약 150 만 건의 기록이 있습니다. –

+0

많은 행과 일치하는'search_term '과 함께 제한을 0으로 사용하는 경우, 빠르지 않을 수있는 모든 행 (잠재적으로 수십만 또는 수백만)을 정렬해야합니다. – mitchellhenke