Redis 위에 있는 검색 엔진인 RediSearch를 둘러싼 간단하지만 강력한 Ruby 래퍼입니다.
먼저 Redis와 RediSearch를 설치해야 합니다.
https://redis.io/download에서 Redis를 다운로드하고 여기에서 설치 지침을 확인할 수 있습니다. 또는 macOS 또는 Linux에서는 Homebrew를 통해 설치할 수 있습니다.
RediSearch를 설치하려면 https://oss.redislabs.com/redisearch/Quick_Start.html을 확인하세요. RediSearch를 빌드한 후 Docker를 사용하지 않는 경우 redis.conf 파일을 업데이트하여 항상 loadmodule /path/to/redisearch.so
사용하여 RediSearch 모듈을 로드할 수 있습니다. (macOS에서는 redis.conf 파일은 /usr/local/etc/redis.conf
에서 찾을 수 있습니다)
Redis와 RediSearch가 실행된 후 Gemfile에 다음 줄을 추가합니다.
gem 'redi_search'
그런 다음:
❯ bundle
아니면 직접 설치하세요:
❯ gem install redi_search
그리고 그것을 요구합니다:
require 'redi_search'
gem이 설치되고 요구되면 Redis 구성으로 이를 구성해야 합니다. Rails를 사용한다면 초기화 프로그램( config/initializers/redi_search.rb
)에 들어가야 합니다.
RediSearch . configure do | config |
config . redis_config = {
host : "127.0.0.1" ,
port : "6379"
}
end
RediSearch는 검색 색인을 중심으로 진행되므로 검색 색인이 무엇인지 정의하는 것부터 시작하겠습니다. Swifttype에 따르면:
검색 색인은 특정 쿼리와 관련된 결과를 찾을 때 검색 엔진이 참조하는 구조화된 데이터 본문입니다. 색인은 검색 엔진 알고리즘의 특정 정보 검색 방법에 맞게 조정되어야 하기 때문에 모든 검색 시스템의 중요한 부분입니다. 이러한 방식으로 알고리즘과 인덱스는 서로 불가분하게 연결됩니다. 인덱스는 검색 엔진 알고리즘에 맞게 구조화된 형식으로 구조화되지 않은 웹사이트 데이터를 수집하는 프로세스를 가리키는 동사(인덱싱)로도 사용할 수 있습니다.
지수에 대해 생각하는 한 가지 방법은 검색 인프라와 사무실 파일링 시스템 간의 다음 비유를 고려하는 것입니다. 인턴에게 수천 장의 종이(문서) 더미를 건네주고 회사가 정보를 보다 효율적으로 찾는 데 도움이 되도록 이 종이 조각을 서류 캐비닛(색인)에 정리하라고 지시한다고 상상해 보십시오. 인턴은 먼저 서류를 분류하고 그 안에 포함된 모든 정보를 파악해야 합니다. 그런 다음 서류 캐비닛에 정리할 시스템을 결정해야 하며 마지막으로 서류가 무엇인지 결정해야 합니다. 캐비닛에 있는 파일을 검색하고 선택하는 가장 효과적인 방법입니다. 이 예에서 논문을 구성하고 제출하는 프로세스는 웹 사이트 콘텐츠를 색인화하는 프로세스에 해당하며, 이러한 정리된 파일을 검색하고 가장 관련성이 높은 파일을 찾는 방법은 검색 알고리즘에 해당합니다.
이는 인덱스에 있는 필드와 해당 필드의 속성을 정의합니다. 스키마는 간단한 DSL입니다. 각 필드는 지역, 숫자, 태그, 텍스트의 네 가지 유형 중 하나일 수 있으며 다양한 옵션을 가질 수 있습니다. 스키마의 간단한 예는 다음과 같습니다.
RediSearch :: Schema . new do
text_field :first_name
text_field :last_name
end
각 유형에 대해 지원되는 옵션은 다음과 같습니다.
옵션 없음: text_field :name
text_field :name, weight: 2
text_field :name, phonetic: 'dm:en'
text_field :name, sortable: true
sortable
과 함께 사용하여 PARTIAL을 사용한 업데이트로 인해 문서가 완전히 다시 색인화되지 않는 필드를 만드는 데 유용합니다. 필드에 no_index
있고 sortable
없으면 인덱스에서 무시됩니다.text_field :name, no_index: true
text_feidl :name, no_stem: true
옵션 없음: numeric_field :price
numeric_field :id, sortable: true
sortable
과 함께 사용하여 PARTIAL을 사용한 업데이트로 인해 문서가 완전히 다시 색인화되지 않는 필드를 만드는 데 유용합니다. 필드에 no_index
있고 sortable
없으면 인덱스에서 무시됩니다.numeric_field :id, no_index: true
옵션 없음: tag_field :tag
tag_field :tag, sortable: true
sortable
과 함께 사용하여 PARTIAL을 사용한 업데이트로 인해 문서가 완전히 다시 색인화되지 않는 필드를 만드는 데 유용합니다. 필드에 no_index
있고 sortable
없으면 인덱스에서 무시됩니다.tag_field :tag, no_index: true
tag_field :tag, separator: ','
옵션 없음: geo_field :place
geo_field :place, sortable: true
sortable
과 함께 사용하여 PARTIAL을 사용한 업데이트로 인해 문서가 완전히 다시 색인화되지 않는 필드를 만드는 데 유용합니다. 필드에 no_index
있고 sortable
없으면 인덱스에서 무시됩니다.geo_field :place, no_index: true
Document
Redis 해시를 Ruby로 표현한 것입니다.
.get
클래스 메소드를 사용하여 Document
가져올 수 있습니다.
get(index, document_id)
주어진 document_id
에 대해 Index
에서 단일 Document
가져옵니다. .for_object(index, record, only: [])
클래스 메소드를 사용하여 Document
인스턴스를 만들 수도 있습니다. Index
인스턴스와 Ruby 객체가 필요합니다. 해당 객체는 Index
의 Schema
에 지정된 모든 필드에 응답해야 합니다. 스키마의 필드 배열 only
허용하고 Document
에 전달되는 필드를 제한합니다.
Document
인스턴스가 있으면 Index
의 Schema
에 메소드 및 document_id
로 지정된 모든 필드에 응답합니다. document_id
고유성을 보장하기 위한 것이 아닌 Index
의 이름 앞에 자동으로 추가됩니다. 서로 다른 Index
에 동일한 ID를 가진 두 개의 Document
가 있는 경우 Document
가 서로 재정의되는 것을 원하지 않기 때문에 Index
이름을 앞에 붙입니다. 앞에 붙은 색인 이름을 제거하는 #document_id_without_index
메소드도 있습니다.
마지막으로 Index
에서 Document
를 제거하는 #del
메소드가 있습니다.
Index
초기화하려면 Index
이름을 문자열이나 기호 및 Schema
블록으로 전달합니다.
RediSearch :: Index . new ( name_of_index ) do
text_field :foobar
end
create
false
반환합니다. 몇 가지 옵션을 허용합니다:max_text_fields: #{true || false}
add_field
사용하여 추가 필드(32개 이상)를 추가할 수 있습니다.no_offsets: #{true || false}
no_highlight
의미합니다.temporary: #{seconds}
seconds
초 동안 활동이 없으면 만료되는 경량 임시 색인을 만듭니다. 내부 유휴 타이머는 인덱스를 검색하거나 추가할 때마다 재설정됩니다. 이러한 인덱스는 가볍기 때문에 성능에 부정적인 영향을 주지 않고 수천 개의 인덱스를 생성할 수 있습니다.no_highlight: #{true || false}
no_highlight
는 no_offsets
에도 적용됩니다.no_fields: #{true || false}
no_frequencies: #{true || false}
drop(keep_docs: false)
Index
삭제하고 부울을 반환합니다. 실패 시 예외를 발생시키는 Bang 메서드가 함께 제공됩니다. Index
이미 삭제된 경우 false
반환합니다. 기본적으로 Redis의 모든 문서 해시를 제거하는 옵션 키워드인 keep_docs
사용합니다.exist?
Index
존재를 나타내는 부울을 반환합니다.info
Index
에 대한 모든 정보가 포함된 구조체 객체를 반환합니다.fields
Index
의 필드 이름 배열을 반환합니다.add(document)
Document
개체를 사용합니다. 실패 시 예외를 발생시키는 Bang 메서드가 함께 제공됩니다.add_multiple(documents)
Document
객체의 배열을 사용합니다. 이는 여러 문서를 Index
에 추가하는 보다 효율적인 방법을 제공합니다. add
와 동일한 옵션을 허용합니다.del(document)
Index
에서 Document
제거합니다.document_count
Index
에 있는 Document
수를 반환합니다.add_field(name, type, **options, &block)
Index
에 새 필드를 추가합니다.index.add_field(:first_name, :text, phonetic: "dm:en")
reindex(documents, recreate: false)
recreate
가 true
이면 Index
가 삭제되고 다시 생성됩니다. 검색은 함께 연결될 수 있는 절이 있는 RediSearch::Index
인스턴스에서 시작됩니다. 검색할 때 모든 스키마 필드에 대한 공개 판독기 메소드가 있는 Document
배열이 반환됩니다.
main ❯ index = RediSearch :: Index . new ( "user_idx" ) { text_field :name , phonetic : "dm:en" }
main ❯ index . add RediSearch :: Document . for_object ( index , User . new ( "10039" , "Gene" , "Volkman" ) )
main ❯ index . add RediSearch :: Document . for_object ( index , User . new ( "9998" , "Jeannie" , "Ledner" ) )
main ❯ index . search ( "john" )
RediSearch ( 1.1 ms ) FT . SEARCH user_idx `john`
=> [ #<RediSearch::Document:0x00007f862e241b78 first: "Gene", last: "Volkman", document_id: "10039">,
#<RediSearch::Document:0x00007f862e2417b8 first: "Jeannie", last: "Ledner", document_id: "9998">]
간단한 구문 쿼리 - hello AND world
index . search ( "hello" ) . and ( "world" )
정확한 구문 쿼리 - hello FOLLOWED BY world
index . search ( "hello world" )
통합 쿼리 - hello OR world
index . search ( "hello" ) . or ( "world" )
부정 쿼리 - hello AND NOT world
index . search ( "hello" ) . and . not ( "world" )
복잡한 교차점 및 결합체:
# Intersection of unions
index . search ( index . search ( "hello" ) . or ( "halo" ) ) . and ( index . search ( "world" ) . or ( "werld" ) )
# Negation of union
index . search ( "hello" ) . and . not ( index . search ( "world" ) . or ( "werld" ) )
# Union inside phrase
index . search ( "hello" ) . and ( index . search ( "world" ) . or ( "werld" ) )
모든 용어는 적용할 수 있는 몇 가지 옵션을 지원합니다.
접두사 용어 : 접두사로 시작하는 모든 용어와 일치합니다. (SQL의 like term%
와 유사)
index . search ( "hel" , prefix : true )
index . search ( "hello worl" , prefix : true )
index . search ( "hel" , prefix : true ) . and ( "worl" , prefix : true )
index . search ( "hello" ) . and . not ( "worl" , prefix : true )
선택적 용어 : 선택적 용어가 포함된 문서는 그렇지 않은 문서보다 순위가 높습니다.
index . search ( "foo" ) . and ( "bar" , optional : true ) . and ( "baz" , optional : true )
퍼지 용어 : Levenshtein 거리(LD)를 기반으로 일치가 수행됩니다. 지원되는 최대 Levenshtein 거리는 3입니다.
index . search ( "zuchini" , fuzziness : 1 )
검색어는 where
절을 사용하여 특정 필드로 범위를 지정할 수도 있습니다.
# Simple field specific query
index . search . where ( name : "john" )
# Using where with options
index . search . where ( first : "jon" , fuzziness : 1 )
# Using where with more complex query
index . search . where ( first : index . search ( "bill" ) . or ( "bob" ) )
숫자 필드 검색에는 범위가 사용됩니다.
index . search . where ( number : 0 .. 100 )
# Searching to infinity
index . search . where ( number : 0 .. Float :: INFINITY )
index . search . where ( number : - Float :: INFINITY .. 0 )
slop(level)
in_order
slop
과 함께 사용됩니다. 쿼리 용어 사이의 오프셋에 관계없이 쿼리 용어가 쿼리에서와 동일한 순서로 Document
에 나타나는지 확인합니다.no_content
Document
ID만 반환합니다. 이는 Document
속성이 중요하지 않고 ActiveRecord
객체로 변환되는 Rails 모델에서 RediSearch를 사용하는 경우 유용합니다.language(language)
Document
를 중국어로 쿼리하는 경우 쿼리 용어를 적절하게 토큰화하려면 중국어로 설정해야 합니다. 지원되지 않는 언어가 전송되면 명령은 오류를 반환합니다.sort_by(field, order: :asc)
:asc
또는 :desc
입니다.limit(num, offset = 0)
offset
에서 지정된 num
으로 제한합니다. 기본 제한은 10
으로 설정됩니다.count
Document
수를 반환합니다.highlight(fields: [], opening_tag: "<b>", closing_tag: "</b>")
fields
강조표시할 필드의 배열입니다.verbatim
no_stop_words
with_scores
Document
의 상대적 내부 점수를 포함합니다. 이는 여러 인스턴스의 결과를 병합하는 데 사용할 수 있습니다. 그러면 반환된 Document
인스턴스에 score
메서드가 추가됩니다.return(*fields)
Document
에서 반환되는 필드를 제한합니다.explain
맞춤법 검사는 RediSearch::Index
인스턴스에서 시작되며 맞춤법이 틀린 검색어에 대한 제안을 제공합니다. 철자 제안을 위한 최대 Levenshtein 거리인 선택적 distance
인수를 사용합니다. 각 요소에 각 검색어에 대한 제안 사항과 인덱스에서의 해당 항목에 따른 정규화된 점수가 포함된 배열을 반환합니다.
main ❯ index = RediSearch :: Index . new ( "user_idx" ) { text_field :name , phonetic : "dm:en" }
main ❯ index . spellcheck ( "jimy" )
RediSearch ( 1.1 ms ) FT . SPELLCHECK user_idx jimy DISTANCE 1
=> [ #<RediSearch::Spellcheck::Result:0x00007f805591c670
term : "jimy" ,
suggestions :
[ #<struct RediSearch::Spellcheck::Suggestion score=0.0006849315068493151, suggestion="jimmy">,
#<struct RediSearch::Spellcheck::Suggestion score=0.00019569471624266145, suggestion="jim">]>]
main ❯ index . spellcheck ( "jimy" , distance : 2 ) . first . suggestions
RediSearch ( 0.5 ms ) FT . SPELLCHECK user_idx jimy DISTANCE 2
=> [ #<struct RediSearch::Spellcheck::Suggestion score=0.0006849315068493151, suggestion="jimmy">,
#<struct RediSearch::Spellcheck::Suggestion score=0.00019569471624266145, suggestion="jim">]
Rails와의 통합은 매우 쉽습니다! 모델 내부에서 schema
키워드 인수를 사용하여 redi_search
호출하세요. 전:
class User < ApplicationRecord
redi_search do
text_field :first , phonetic : "dm:en"
text_field :last , phonetic : "dm:en"
end
end
그러면 Index
인스턴스에서 호출한 것과 동일하게 동작하는 User.search
및 User.spellcheck
메소드가 자동으로 추가됩니다.
User.reindex(recreate: false, only: [])
도 추가되었으며 RediSearch::Index#reindex
와 유사하게 동작합니다. 몇 가지 차이점은 다음과 같습니다.
Document
는 첫 번째 매개변수로 전달될 필요가 없습니다. search_import
범위가 자동으로 호출되고 모든 레코드가 Document
로 변환됩니다.only
매개변수를 허용합니다. 스키마를 변경하고 특정 필드만 색인화해야 하는 경우 유용합니다. 스키마를 정의하는 동안 선택적으로 스키마에 블록을 전달할 수 있습니다. 블록이 전달되지 않으면 모델에서 name
호출되어 값을 얻습니다. 블록이 전달되면 블록 호출을 통해 필드 값을 얻습니다.
class User < ApplicationRecord
redi_search do
text_field :name do
" #{ first_name } #{ last_name } "
end
end
end
인덱싱 시 관계를 즉시 로드하도록 모델의 search_import
범위를 재정의하거나 인덱스할 레코드를 제한하는 데 사용할 수 있습니다.
class User < ApplicationRecord
scope :search_import , -> { includes ( :posts ) }
end
검색할 때 기본적으로 Document
컬렉션이 반환됩니다. 검색 쿼리에 대해 #results
호출하면 검색이 실행된 다음 데이터베이스에서 발견된 모든 레코드를 조회하고 ActiveRecord 관계를 반환합니다.
모델 Index
의 기본 Index
이름은 #{model_name.plural}_#{RediSearch.env}
입니다. redi_search
메소드는 인덱스 이름 앞에 추가되는 선택적 index_prefix
인수를 사용합니다.
class User < ApplicationRecord
redi_search index_prefix : 'prefix' do
text_field :first , phonetic : "dm:en"
text_field :last , phonetic : "dm:en"
end
end
User . search_index . name
# => prefix_users_development
RediSearch를 모델에 통합할 때 레코드는 생성 및 업데이트 후 자동으로 색인화되고 파기 시 Index
에서 제거됩니다.
공개적으로 사용 가능한 몇 가지 편의 방법이 더 있습니다.
search_document
RediSearch::Document
인스턴스로 반환합니다.remove_from_index
Index
에서 레코드를 제거합니다.add_to_index
Index
에 레코드를 추가합니다.search_index
RediSearch::Index
인스턴스를 반환합니다. 저장소를 확인한 후 bin/setup
실행하여 종속 항목을 설치하세요. 그런 다음 rake test
실행하여 단위 테스트와 통합 테스트를 모두 실행합니다. 개별적으로 실행하려면 rake test:unit
또는 rake test:integration
실행하면 됩니다. 실험할 수 있는 대화형 프롬프트를 보려면 bin/console
실행할 수도 있습니다.
이 gem을 로컬 머신에 설치하려면, bundle exec rake install
실행하세요. 새 버전을 릴리스하려면 version.rb
의 버전 번호를 업데이트하는 bin/publish (major|minor|patch)
실행하고, 해당 버전에 대한 git 태그를 생성하고, git 커밋 및 태그를 푸시하고, .gem
파일을 rubygems에 푸시하세요. .org 및 GitHub.
버그 보고서와 끌어오기 요청은 GitHub에서 환영합니다. 이 프로젝트는 협업을 위한 안전하고 환영받는 공간이 되도록 의도되었으며 기여자는 기여자 규약 행동 강령을 준수해야 합니다.
이 gem은 MIT 라이선스 조건에 따라 오픈 소스로 제공됩니다.
RediSearch 프로젝트의 코드베이스, 이슈 추적기, 채팅방 및 메일링 목록에서 상호 작용하는 모든 사람은 행동 강령을 따라야 합니다.