غلاف روبي بسيط ولكنه قوي حول RediSearch، وهو محرك بحث أعلى Redis.
أولاً، يجب تثبيت Redis وRediSearch.
يمكنك تنزيل Redis من https://redis.io/download، والتحقق من تعليمات التثبيت هنا. وبدلاً من ذلك، على نظام التشغيل macOS أو Linux، يمكنك التثبيت عبر Homebrew.
لتثبيت RediSearch، قم بالتحقق من https://oss.redislabs.com/redisearch/Quick_Start.html. بمجرد الانتهاء من إنشاء RediSearch، إذا كنت لا تستخدم Docker، يمكنك تحديث ملف redis.conf الخاص بك لتحميل وحدة RediSearch دائمًا باستخدام loadmodule /path/to/redisearch.so
. (على نظام التشغيل macOS، يمكن العثور على ملف redis.conf على /usr/local/etc/redis.conf
)
بعد تشغيل Redis وRediSearch، أضف السطر التالي إلى ملف Gemfile الخاص بك:
gem 'redi_search'
وثم:
❯ bundle
أو قم بتثبيته بنفسك:
❯ gem install redi_search
وتطلب ذلك:
require 'redi_search'
بمجرد تثبيت الجوهرة والمطلوبة، ستحتاج إلى تهيئتها باستخدام تكوين Redis الخاص بك. إذا كنت تستخدم Rails، فيجب أن يتم ذلك في مُهيئ ( config/initializers/redi_search.rb
).
RediSearch . configure do | config |
config . redis_config = {
host : "127.0.0.1" ,
port : "6379"
}
end
يتمحور RediSearch حول فهرس البحث، لذا فلنبدأ بتعريف فهرس البحث. وفقًا لـ Swiftype:
فهرس البحث عبارة عن مجموعة من البيانات المنظمة التي يشير إليها محرك البحث عند البحث عن نتائج ذات صلة باستعلام محدد. تعد الفهارس جزءًا مهمًا من أي نظام بحث، حيث يجب أن تكون مصممة خصيصًا لطريقة استرجاع المعلومات المحددة لخوارزمية محرك البحث. بهذه الطريقة، ترتبط الخوارزمية والفهرس ببعضهما البعض بشكل لا ينفصم. يمكن أيضًا استخدام الفهرس كفعل (فهرسة)، في إشارة إلى عملية جمع بيانات موقع الويب غير المنظمة بتنسيق منظم مصمم خصيصًا لخوارزمية محرك البحث.
إحدى طرق التفكير في المؤشرات هي النظر في القياس التالي بين البنية التحتية للبحث ونظام حفظ الملفات المكتبي. تخيل أنك سلمت أحد المتدربين مجموعة من آلاف قطع الورق (المستندات) وتطلب منه تنظيم هذه القطع من الورق في خزانة الملفات (الفهرس) لمساعدة الشركة في العثور على المعلومات بشكل أكثر كفاءة. سيتعين على المتدرب أولاً فرز الأوراق والتعرف على جميع المعلومات الموجودة بداخلها، ثم سيتعين عليه اتخاذ قرار بشأن نظام لترتيبها في خزانة الملفات، ثم سيتعين عليه أخيرًا تحديد ما هو الطريقة الأكثر فعالية للبحث في الملفات والاختيار منها بمجرد وجودها في الخزانة. في هذا المثال، تتوافق عملية تنظيم الأوراق وحفظها مع عملية فهرسة محتوى موقع الويب، وتتوافق طريقة البحث عبر هذه الملفات المنظمة والعثور على الملفات الأكثر صلة مع خوارزمية البحث.
وهذا يحدد الحقول وخصائص تلك الحقول في الفهرس. المخطط هو 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.
يمكنك جلب Document
باستخدام أساليب فئة .get
.
get(index, document_id)
بجلب Document
واحد في Index
لمستند معين document_id
. يمكنك أيضًا إنشاء نسخة Document
باستخدام طريقة الفئة .for_object(index, record, only: [])
. يستغرق مثيل Index
وكائن روبي. يجب أن يستجيب هذا الكائن لكافة الحقول المحددة في Schema
Index
. يقبل only
مجموعة من الحقول من المخطط ويحد من الحقول التي تم تمريرها إلى Document
.
بمجرد أن يكون لديك مثيل Document
، فإنه يستجيب لجميع الحقول المحددة في Schema
Index
مثل الأساليب و document_id
. يتم إضافة document_id
تلقائيًا إلى أسماء Index
ما لم يكن ذلك لضمان التفرد بالفعل. نحن نعلق اسم Index
مسبقًا لأنه إذا كان لديك Document
بنفس المعرف في Index
مختلف، فلا نريد أن تتجاوز Document
بعضها البعض. هناك أيضًا طريقة #document_id_without_index
والتي تزيل اسم الفهرس المُعلق مسبقًا.
وأخيرا هناك طريقة #del
التي ستزيل Document
من Index
.
لتهيئة Index
، قم بتمرير اسم Index
كسلسلة أو رمز وكتلة Schema
.
RediSearch :: Index . new ( name_of_index ) do
text_field :foobar
end
create
false
إذا كان الفهرس موجودًا بالفعل. يقبل بعض الخيارات:max_text_fields: #{true || false}
add_field
.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
من نسخة Redis، ويعيد قيمة منطقية. لديه طريقة فرقعة مصاحبة من شأنها أن تثير استثناء عند الفشل. سيعود false
إذا تم إسقاط Index
بالفعل. يأخذ الخيار الكلمة الأساسية arg، keep_docs
، والتي ستقوم افتراضيًا بإزالة كافة تجزئات المستند في Redis.exist?
Index
.info
Index
.fields
Index
.add(document)
Document
. لديه طريقة فرقعة مصاحبة من شأنها أن تثير استثناء عند الفشل.add_multiple(documents)
Document
. وهذا يوفر طريقة أكثر كفاءة لإضافة مستندات متعددة إلى Index
. يقبل نفس خيارات add
.del(document)
Document
من Index
.document_count
Document
في Index
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" ) )
تدعم جميع المصطلحات بعض الخيارات التي يمكن تطبيقها.
مصطلحات البادئة : مطابقة جميع المصطلحات التي تبدأ ببادئة. (أشبه like term%
في SQL)
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 )
المصطلحات الغامضة : يتم إجراء المباريات بناءً على مسافة ليفنشتاين (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
فقط وليس المحتوى. يعد هذا مفيدًا إذا تم استخدام RediSearch في نموذج Rails حيث لا تهم سمات Document
ويتم تحويله إلى كائنات ActiveRecord
.language(language)
Document
باللغة الصينية، فيجب ضبط هذا على اللغة الصينية من أجل ترميز مصطلحات الاستعلام بشكل صحيح. إذا تم إرسال لغة غير مدعومة، فسيقوم الأمر بإرجاع خطأ.sort_by(field, order: :asc)
:asc
أو :desc
limit(num, offset = 0)
num
المحدد في offset
. تم تعيين الحد الافتراضي على 10
.count
Document
الموجودة في استعلام البحثhighlight(fields: [], opening_tag: "<b>", closing_tag: "</b>")
fields
هي مجموعة من الحقول التي سيتم تسليط الضوء عليها.verbatim
no_stop_words
with_scores
Document
. يمكن استخدام هذا لدمج النتائج من حالات متعددة. سيؤدي هذا إلى إضافة طريقة score
إلى مثيلات Document
التي تم إرجاعها.return(*fields)
Document
.explain
يتم بدء التدقيق الإملائي من مثيل RediSearch::Index
ويقدم اقتراحات لمصطلحات البحث التي بها أخطاء إملائية. يستغرق الأمر وسيطة distance
اختيارية وهي مسافة Levenshtein القصوى لاقتراحات التدقيق الإملائي. تقوم بإرجاع مصفوفة حيث يحتوي كل عنصر على اقتراحات لكل مصطلح بحث ودرجة موحدة بناءً على حدوثه في الفهرس.
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 سهل للغاية! اتصل بـ redi_search
باستخدام وسيطة الكلمة الأساسية schema
من داخل النموذج الخاص بك. السابق:
class User < ApplicationRecord
redi_search do
text_field :first , phonetic : "dm:en"
text_field :last , phonetic : "dm:en"
end
end
سيؤدي هذا تلقائيًا إلى إضافة أساليب User.search
و User.spellcheck
التي تتصرف بنفس الطريقة كما لو قمت باستدعائها على مثيل Index
.
تمت إضافة 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
للحصول على مطالبة تفاعلية تسمح لك بالتجربة.
لتثبيت هذه الجوهرة على جهازك المحلي، قم بتشغيل bundle exec rake install
. لإصدار إصدار جديد، قم بتنفيذ bin/publish (major|minor|patch)
الذي سيؤدي إلى تحديث رقم الإصدار في version.rb
، وإنشاء علامة git للإصدار، ودفع التزامات git وعلاماته، ودفع ملف .gem
إلى Rubygems .org وجيثب.
نرحب بتقارير الأخطاء وطلبات السحب على GitHub. يهدف هذا المشروع إلى أن يكون مساحة آمنة ومرحبة للتعاون، ومن المتوقع أن يلتزم المساهمون بمدونة قواعد السلوك الخاصة بعهد المساهمين.
الجوهرة متاحة كمصدر مفتوح بموجب شروط ترخيص MIT.
من المتوقع أن يتبع كل من يتفاعل في قواعد التعليمات البرمجية لمشروع RediSearch ومتتبعي المشكلات وغرف الدردشة والقوائم البريدية قواعد السلوك.