কম্পিউটার টিউটোরিয়াল

রেইলস অ্যাপ বাড়ান: ইলাস্টিকসার্চ দিয়ে ফুল-টেক্সট সার্চ মাস্টার করুন

ইলাস্টিকসার্চ (Elasticsearch) বর্তমান বিশ্বের সবচেয়ে জনপ্রিয় সার্চ ইঞ্জিনের একটি। নেটফ্লিক্স (Netflix), মিডিয়াম (Medium), গিটহাব (GitHub) এর মতো অনেক বড় কোম্পানি এটি প্রোডাকশনে সক্রিয়ভাবে ব্যবহার করে।

ইলাস্টিকসারখ খুব শক্তিশালী, এর প্রধান ব্যবহারের ক্ষেত্রে রয়েছে: ফুল-টেক্সট সার্চ (full-text search), রিয়েল-টাইম লগ অ্যানালিটিক্স, এবং সিকিউরিটি অ্যানালসিস।

দুর্ভাগ্যক্রমে, রেইলস (Rails) কমিউনিটিতে ইলাস্টিকসার্চ उतना মনোযোগ পায় না, তাই এই আর্টিকেল দুটি লক্ষ্যে লেখা: পাঠকদের ইলাস্টিকসার্ভ কনসেপ্ট পরিচিত করানো এবং রুবি অন রেইলস (Ruby on Rails) এর সাথে এটি কীভাবে ব্যবহার করতে হয় তা দেখানো।

আমরা যে উদাহরণ প্রজেক্টটি তৈরি করব তার সোর্স কোড এখানে পাবেন। কমিট ইতিহাস कमোবেশ এই আর্টিকেলের সেকশনগুলির ক্রম অনুযায়ী।

পরিচয়

ব্রডার পারস্পেক্টিভ থেকে, ইলাস্টিকসার্চ একটি সার্চ ইঞ্জিন যা:

  • Apache Lucene-এর ওপর নির্মিত;
  • JSON ডকুমেন্ট সংরক্ষণ এবং কার্যকরভাবে ইনডেক্স করে;
  • ওপেন-सোর্স;
  • এবং এর সাথে ইন্টারঅ্যাক্ট করার জন্য REST APIs প্রদান করে;
  • ডিফল্টভাবে কোনো সিকিউরিটি নেই (যে কেউ পাবলিক এন্ডপয়েন্টের মাধ্যমে কোয়েরি করতে পারে);
  • হরিজন্টালি খুব ভালো স্কেল করে।

চলুন কিছু বেসিক কনসেপ্ট দ্রুত দেখে নিই।

ইলাস্টিকসার্চে, আমরা ডকুমেন্টগুলো ইন্ডেক্সে (indices) রাখি, যা পরে ডেটা কোয়েরি করার জন্য ব্যবহার করা হয়।

একটি ইন্ডেক্স (index) রিলেশনাল ডেটাবেসের টেবিলের মতো; এটি একটি স্টোর যেখানে আমরা ডকুমেন্ট (রো) রাখি যা পরে কোয়েরি করা যায়।

একটি ডকুমেন্ট (document) হলো ফিল্ডগুলোর সংগ্রহ (রিলেশনাল ডেটাবেসের রোর মতো)।

এক ম্যাপিং (mapping) রিলেশনাল ডেটাবেসের স্কিমা ডেফিনিশনের মতো। ম্যাপিং স্পষ্টভাবে ডিফাইন করা যেতে পারে অথবা ইলাস্টিকসার্চ ইনসার্ট করার সময় অনুমান করতে পারে; সবসময় ইন্ডেক্স ম্যাপিং আগে থেকে ডিফাইন করা ভালো।

এটি কভার হয়ে গেলে, এখন আমাদের এনভায়রনমেন্ট সেট আপ করা যাক।

ইলাস্টিকসার্চ ইনস্টল করা

macOS-এ ইলাস্টিকসার্চ ইনস্টল করার সবচেয়ে সহজ উপায় হলো brew ব্যবহার করা:

brew tap elastic/tap
brew install elastic/tap/elasticsearch-full

বিকল্পভাবে, আমরা ডকার (Docker) ব্যবহার করে চালাতে পারি:

docker run \
-p 127.0.0.1:9200:9200 \
-p 127.0.0.1:9300:9300 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:7.16.2

অন্যান্য অপশন জন্য অফিসিয়াল রেফারেন্স দেখুন।

ইলাস্টিকসার্চ ডিফল্টভাবে পোর্ট ৯২০০-এ রিকোয়েস্ট গ্রহণ করে। এটি চলছে কিনা একটি সিম্পল curl রিকোয়েস্ট দিয়ে (বা ব্রাউজারে খুলে) চেক করা যায়:

curl https://localhost:9200

API সমূহ

ইলাস্টিকসার্চ প্রতিটি সম্ভব টাস্কের জন্য REST APIs প্রদান করে। উদাহরণস্বরূপ, ধরুন আমরা একটি JSON কন্টেন্ট টাইপের সাথে POST রিকোয়েস্ট চালিয়ে একটি ডকুমেন্ট তৈরি করি:

curl -X POST https://localhost:9200/my-index/_doc \
-H 'Content-Type: application/json' \
-d '{"title": "Banana Cake"}'

এখানে, my-index হলো একটি ইন্ডেক্সের নাম (যদি না থাকে, তবে অটোমেটিক তৈরি হয়)।

_doc হলো একটি সিস্টেম রাউট (সকল সিস্টেম রাউট আন্ডারস্কোর দিয়ে শুরু হয়)।

API-গুলোর সাথে ইন্টারঅ্যাক্ট করার একাধিক উপায় আছে:

  1. কমান্ড-লাইন থেকে curl ব্যবহার করা (আপনি jq কাজে লাগতে পারেন)।
  2. ব্রাউজার থেকে GET কোয়েরি চালানো, JSON প্রিটি প্রিন্টিং এক্সটেনশন ব্যবহার করে।
  3. Kibana ইনস্টল করে Dev Tools কনসোল ব্যবহার করা, যা আমার প্রিয় পদ্ধতি।
  4. অতিরিক্ত কিছু চমৎকার Chrome এক্সটেনশন রয়েছে।

এই আর্টিকেলের জন্য কোন পদ্ধতি বেছে নেওয়া হোক, 상관 নেই—কেননা আমরা সরাসরি API-র সাথে ইন্টারঅ্যাক্ট করব না। বরং আমরা একটি জেম (gem) ব্যবহার করব, যা পিছনে REST API-র সাথে কথা বলে।

নতুন অ্যাপ শুরু করা

আইডিয়া হলো একটি সাংগ লিরিক্স অ্যাপ্লিকেশন তৈরি করা ২৬,০০০+ গানের একটি পাবলিক ডেটাসেট ব্যবহার করে। প্রতিটি গানের আছে title, artist, genre, এবং lyrics ফিল্ড। আমরা ইলাস্টিকসার্চ ব্যবহার করব ফুল-টেক্সট সার্চের জন্য।

চলুন একটি সিম্পল রেইলস অ্যাপ্লিকেশন তৈরি করি:

rails new songs_api --api -d postgresql

যেহেতু আমরা শুধু API হিসেবে ব্যবহার করব, --api ফ্ল্যাগ দিয়ে মিডলওয়্যার সেট সীমিত করা হয়েছে।

এখন অ্যাপ স্ক্যাফোল্ড (scaffold) করি:

bin/rails generate scaffold Song title:string artist:string genre:string lyrics:text

মাইগ্রেশন চালিয়ে সার্ভার শুরু করি:

bin/rails db:create db:migrate
bin/rails server

এরপর, GET এন্ডপয়েন্ট কাজ করছে কিনা যাচাই করি:

curl https://localhost:3000/songs

এটি একটি খালি অ্যারে রিটার্ন করবে, কারণ এখনো কোনো ডেটা নেই।

ইলাস্টিকসার্চ পরিচিতি

এখন ইলাস্টিকসার্খ যোগ করি। এর জন্য elasticsearch-model জেমটি লাগবে। এটি একটি অফিসিয়াল ইলাস্টিকসার্চ জেম যা রেইলস মডেলের সাথে ভালোভাবে ইন্টিগ্রেট হয়।

আপনার Gemfile-এ নিচের লাইনটি যোগ করুন:

gem 'elasticsearch-model'

ডিফল্টভাবে এটি লোকালহোস্টের পোর্ট ৯২০০-এ কানেক্ট হবে, যা আমাদের জন্য পরফেক্ট। যদি চান তবে ক্লায়েন্ট ইনিশিয়ালাইজ করে পরিবর্তন করতে পারেন:

Song.__elasticsearch__.client = Elasticsearch::Client.new host: 'myserver.com', port: 9876

এরপর, আমাদের মডেলকে ইলাস্টিকসার্চের দ্বারা ইনডেক্সযোগ্য করার জন্য দুটি কাজ করতে হবে। প্রথমে, একটি ম্যাপিংเตয়ারি করতে হবে (যা মূলত ইলাস্টিকসার্চকে আমাদের ডেটা স্ট্রাকচার সম্পর্কে জানানো), এবং দ্বিতীয়ত, একটি সার্চ রিকোয়েস্ট কনস্ট্রাক্ট করতে হবে। আমাদের জেম দুটি কাজই করতে পারে, চলুন দেখি কীভাবে ব্যবহার করব।

ইলাস্টিকসার্চ-রিলেটেড কোড আলাদা একটি মডিউলে রাখা ভালো অভ্যাস, তাই app/models/concerns/searchable.rb এ একটি কনসার্ন (concern) তৈরি করি এবং নিচের কোড যোগ করি:

# app/models/concerns/searchable.rb
module Searchable
  extend ActiveSupport::Concern

  included do
    include Elasticsearch::Model
    include Elasticsearch::Model::Callbacks

    mapping do
      # mapping definition goes here
    end

    def self.search(query)
      # build and run search
    end
  end
end

এটি শুধু একটি স্কেলেটন হলেও, এখানে কিছু অনর্যাভ করতে আছে।

সবচেয়ে গুরুত্বপূর্ণ হলো Elasticsearch::Model, যা ES-র সাথে ইন্টারঅ্যাক্ট করার ফাংশন্যালিটি যোগ করে। Elasticsearch::Model::Callbacks মডিউল নিশ্চিত করে যে যখন আমরা একটি রেকর্ড আপডেট করি, এটি অটোমেটিক্যালি ইলাস্টিকসার্চের ডেটা আপডেট করে। mapping ব্লকে আমরা ইলাস্টিকসার্চ ইন্ডেক্স ম্যাপিং রাখি, যা ডিফাইন করে কী ফিল্ডগুলো ইলাস্টিকসার্চে সংরক্ষিত হবে এবং তাদের টাইপ কী হবে। অবশেষে, একটি search মেথড যা আমরা সांग লিরিক্স সার্চ করার জন্য ব্যবহার করব। আমরা যে জেমটি ব্যবহার করছি সেটি একটি search মেথড প্রদান করে যা সিম্পল কোয়েরি যেমন Song.search("genesis") দিয়ে ব্যবহার করা যায়, কিন্তু আমরা এটি কোয়েরি DSL ব্যবহার করে আরও জটিল সার্চ কোয়েরি কনস্ট্রাক্ট করব (বादে আরো বিস্তারিত)।

কনসার্নটি আমাদের মডেল ক্লাসে ইনক্লুড করা ভুলবেন না:

# /app/models/song.rb
class Song < ApplicationRecord
  include Searchable
end

ম্যাপিং সমূহ

ইলাস্টিকসার্চে, ম্যাপিং রিলেশনাল ডেটাবেসের স্কিমা ডেফিনিশনের মতো। আমরা ডকুমেন্টের স্ট্রাকচার বর্ণনা করি যা আমরা স্টোর করতে চাই। সাধারণ রিলেশনাল ডেটাবেসের বিপরীতে, আমাদের ম্যাপিং আগে থেকে ডিফাইন করতে হয় না: ইলাস্টিকসার্চ তার সেরা দিয়ে টাইপ অনুমান করার চেষ্টা করে। তবুও, সারপ্রাইজ এড়াতে আমরা স্পষ্টভাবে ম্যাপিং আগে থেকে ডিফাইন করব।

ম্যাপিং আপডেট করা যায় REST এন্ডপয়েন্ট ব্যবহার করে PUT /my-index/_mapping এবং পড়া যায় GET /my-index/_mapping দিয়ে, কিন্তু elasticsearch জেমটি আমাদের জন্য এটি অ্যাবস্ট্রাক্ট করে দিয়েছে, তাই আমাদের শুধু mapping ব্লকটি প্রদান করলেই চলে।

# app/models/concerns/searchable.rb
mapping do
  indexes :artist, type: :text
  indexes :title, type: :text
  indexes :lyrics, type: :text
  indexes :genre, type: :keyword
end

আমরা artist, title, এবং lyrics ফিল্ডগুলো text টাইপ ব্যবহার করে ইনডেক্স করব। ফুল-টেক্সট সার্চের জন্য ইন্ডেক্স হওয়া একমাত্র টাইপ হলো text। genre-র জন্য আমরা keyword টাইপ ব্যবহার করব, যা সঠিক মান দিয়ে ফিল্টার করার জন্য আদর্শ।

এখন রেইলস কনসোল চালু করুন bin/rails console দিয়ে এবং তারপর চালান:

Song.__elasticsearch__.create_index!

এটি ইলাস্টিকসার্চে আমাদের ইন্ডেক্স তৈরি করবে। __elasticsearch__ অবজেক্টটি ইলাস্টিকসার্চ বিশ্বের গেটওয়ে, যেটিতে ইন্টারঅ্যাক্ট করার জন্য অনেক উপকারী মেথড রয়েছে।

ডেটা ইম্পোর্ট করা

প্রতিবার একটি রেকর্ড তৈরি করলে, এটি অটোমেটিক্যালি ডেটা ইলাস্টিকসার্চে পাঠাবে। তাই আমরা সাংগ লিরিক্সের একটি ডেটাসেট ডাউনলোড করব এবং আমাদের অ্যাপে ইম্পোর্ট করব। প্রথমে, এই লিংক থেকে ডাউনলোড করুন (একটি ডেটাসেট যা Creative Commons Attribution 4.0 International license-এর অধীনে)। এই CSV ফাইলে ২৬,০০০+ রেকর্ড রয়েছে, যা আমরা নিচের কোড দিয়ে আমাদের ডেটাবেস এবং ইলাস্টিকসার্চে ইম্পোর্ট করব:

require 'csv'
class Song < ApplicationRecord
  include Searchable
  def self.import_csv!
    filepath = "/path/to/your/file/tcc_ceds_music.csv"
    res = CSV.parse(File.read(filepath), headers: true)
    res.each_with_index do |s, ind|
      Song.create!(
        artist: s["artist_name"],
        title: s["track_name"],
        genre: s["genre"],
        lyrics: s["lyrics"]
      )
    end
  end
end

রেইলস কনসোল খুলুন এবং Song.import_csv! চালান (এটি কিছুক্ষণ সময় নেবে)। বিকল্পভাবে, আমরা বাল্ক (bulk) ইম্পোর্ট করতে পারতাম, যা খুব দ্রুত, কিন্তু এই কেসে আমরা চাই যে PostgreSQL ডেটাবেস এবং ইলাস্টিকসার্চ দুটোই রেকর্ড তৈরি হয়।

ইম্পোর্ট শেষ হলে, আমাদের पास সার্চ করার জন্য প্রচুর লিরিক্স থাকবে।

ডেটা সার্চ করা

elasticsearch-model জেমটি একটি search মেথড যোগ করে যা সকল ইনডেক্সড ফিল্ডের মধ্যে সার্চ করতে দেয়। এটিকে আমাদের searchable কনসার্নে ব্যবহার করি:

# app/models/concerns/searchable.rb
# ...
def self.search(query)
  self.__elasticsearch__.search(query)
end
# ...

রেইলস কনসোল খুলুন এবং res = Song.search('genesis') চালান। রেসপন্স অবজেক্টে অনেক মেটা ইনফরমেশন থাকে: রিকোয়েস্টে কতো সময় লাগল, কোন নোডগুলো ব্যবহার হয়েছে, ইত্যাদি। আমাদের আগ্রহ hits-এ, যা res.response["hits"]["hits"]-এ পাওয়া যায়।

চলুন আমাদের কন্ট্রোলারের index মেথড পরিবর্তন করি ES কোয়েরি করার জন্য।

# app/controllers/songs_controller.rb
def index
  query = params["query"] || ""
  res = Song.search(query)
  render json: res.response["hits"]["hits"]
end

এখন ব্রাউজারে বা curl ব্যবহার করে https://localhost:3000/songs?query=genesis লোড করুন। রেসপন্স এমন দেখাবে:

[
  {
    "_index": "songs",
    "_type": "_doc",
    "_id": "22676",
    "_score": 12.540506,
    "_source": {
      "id": 22676,
      "title": "genesis",
      "artist": "grimes",
      "genre": "pop",
      "lyrics": "heart know heart ...",
      "created_at": "...",
      "updated_at": "..."
    }
  },
  ...
]

আপনি দেখতে পাচ্ছেন, আসলে ডেটা _source কী-এর অধীনে রিটার্ন হচ্ছে, বাকি ফিল্ডগুলো মেটাডেটা, 그중 সবচেয়ে গুরুত্বপূর্ণ _score যা দেখায় ডকুমেন্টটি নির্দিষ্ট সার্চের জন্য কতটুকু প্রাসঙ্গিক। এখান থেকে আমরা কোয়েরি করার পদ্ধতি শিখব।

The Query DSL

ইলাস্টিকসার্চ কোয়েরি DSL জটিল কোয়েরি কনস্ট্রাক্ট করার একটি উপায় প্রদান করে, এবং আমরা এটি রুবি কোড থেকে ব্যবহার করতে পারি। উদাহরণস্বরূপ, সার্চ মেথড পরিবর্তন করি শুধু artist ফিল্ডে সার্চ করার জন্য:

# app/models/concerns/searchable.rb
module Searchable
  extend ActiveSupport::Concern
  included do
    # ...
    def self.search(query)
      params = {
        query: {
          match: {
            artist: query,
          },
        },
      }
      self.__elasticsearch__.search(params)
    end
  end
end

query-match কনস্ট্রাক্ট আমাদের শুধু একটি নির্দিষ্ট ফিল্ডে (এই কেসে artist) সার্চ করতে দেয়। এখন আবার "genesis" দিয়ে সার্চ করলে (ট্রাই করুন https://localhost:3000/songs?query=genesis লোড করে), আমরা শুধু "Genesis" ব্যান্ডের গান পাব, نه"title"-এ "genesis" থাকা গান। যদি একাধিক ফিল্ডে কোয়েরি করতে চাই, যা সাধারণত হয়, তবে multi-match কোয়েরি ব্যবহার করুন:

# app/models/concerns/searchable.rb
def self.search(query)
  params = {
    query: {
      multi_match: {
        query: query,
        fields: [ :title, :artist, :lyrics ]
      },
    },
  }
  self.__elasticsearch__.search(params)
end

ফিল্টারিং

যদি আমরা শুধু রক (rock) জ্যানারের গানগুলোর মধ্যে সার্চ করতে চাই? তখন genre দিয়ে ফিল্টার করতে হবে! এটি আমাদের সার্চ কিছুটা জটিল করবে, কিন্তু চিন্তা নেই—ধাপে ধাপে ব্যাখ্যা করব।

def self.search(query, genre = nil)
  params = {
    query: {
      bool: {
        must: [
          { multi_match: { query: query, fields: [ :title, :artist, :lyrics ] } },
        ],
        filter: [
          { term: { genre: genre } }
        ]
      }
    }
  }
  self.__elasticsearch__.search(params)
end

প্রথম নতুন কীওয়ার্ড হলো bool, যা একাধিক কোয়েরিকে একত্রিত করার একটি উপায়। আমাদের কেসে, আমরা must এবং filter একত্রিত করছি। প্রথমটি (must) স্কোরে অবদান রাখে এবং সেম কোয়েরিটি ধারণ করে যা আমরা ইতিমধ্যে ব্যবহার করেছি। দ্বিতীয়টি (filter) স্কোরে অবদান রাখে না, এটি শুধু ফিল্টার করে যা কোয়েরির সাথে মেলে না। আমরা genre দিয়ে রেকর্ড ফিল্টার করতে চাই, তাই term কোয়েরি ব্যবহার করছি।

গুরুত্বপূর্ণ: filter-term কোম্বিনেশন ফুল-টেক্সট সার্চের সাথে কোনো সম্পর্কে নেই। এটি সঠিক মান দিয়ে একটি রেগুলার ফিল্টার, ঠিক SQL-এর WHERE ক্লজের মতো (WHERE genre = 'rock')। term ফিল্টারিং কীভাবে ব্যবহার করবেন তা জানা ভালো, কিন্তু এখানে এর প্রয়োজন নেই।

স্কোরিং

সার্চ রেজাল্ট _score অনুযায়ী অর্ডার করা হয় যা দেখায় একটি আইটেম নির্দিষ্ট সার্চের জন্য কতটুকু প্রাসঙ্গিক। যত বেশি স্কোর, তত বেশি প্রাসঙ্গিক ডকুমেন্ট। আপনি লক্ষ্য করেছেন হবে, যখন আমরা genesis শব্দটি সার্চ করলাম, প্রথম রেজাল্ট আসল Grimes-এর গান, কিন্তু আমি আসলে Genesis ব্যান্ডে আরও আগ্রহী ছিলাম। তো, কি আমরা স্কোরিং মেকানিজম পরিবর্তন করে artist ফিল্ডে বেশি গুরুত্ব দিতে পারি? হ্যাঁ, পারি, কিন্তু তার জন্য কোয়েরি টвиক করতে হবে:

def self.search(query)
  params = {
    query: {
      bool: {
        should: [
          { match: { title: query }},
          { match: { artist: query }},
          { match: { lyrics: query }},
        ],
      },
    },
  }
  self.__elasticsearch__.search(params)
end

এই কোয়েরি মূলত সাবেকটির সমতুল্য বসুলে bool কীওয়ার্ড ব্যবহার করছে, যা একাধিক কোয়েরি একত্রিত করার উপায়। এখানে should ব্যবহার করা হয়েছে, যাতে তিনটি কোয়েরি পৃথক থাকে (প্রতি ফিল্ডে একটি): এগুলো লজিক্যাল OR দিয়ে কম্বাইন হয়। যদি must ব্যবহার করতাম, তবে লজিক্যাল AND দিয়ে কম্বাইন হতো। পৃথক match প্রতি ফিল্ডে কেন? কারণ এখন আমরা boost প্রপার্টি নির্দিষ্ট করতে পারি, যা নির্দিষ্ট কোয়েরির স্কোরকে গুণ করে একটি কোইফিশিয়েন্ট:

def self.search(query)
  params = {
    query: {
      bool: {
        should: [
          { match: { title: query }},
          { match: { artist: { query: query, boost: 5 } }},
          { match: { lyrics: query }},
        ],
      },
    },
  }
  self.__elasticsearch__.search(params)
end

অন্য সব সমান থাকলে, আর্টিস্টের সাথে কোয়েরি মেললে আমাদের স্কোর পাঁচ গুণ বেশি হবে। আবার genesis কোয়েরি ট্রাই করুন https://localhost:3000/songs?query=genesis দিয়ে, এবং আপনি দেখবেন Genesis ব্যান্ডের গানগুলো প্রথমে আসছে। সুইট!

হাইলাইটিং

ইলাস্টিকসার্চের আর একটি কার্যকর ফিচার হলো ডকুমেন্টের ভেতরে ম্যাচ হাইলাইট করা, যা ইউজারকে ভালোভাবে বুঝতে দেয় কেন একটি নির্দিষ্ট রেজাল্ট সার্চে আসেছে।

HTML-এ এর জন্য একটি স্পেশাল ট্যাগ রয়েছে, এবং ইলাস্টিকসার্চ এটি অটোমেটিক্যালি যোগ করতে পারে।

আবার searchable.rb কনসার্ন খুলুন এবং একটি নতুন কীওয়ার্ড যোগ করুন:

def self.search(query)
  params = {
    query: {
      bool: {
        should: [
          { match: { title: query }},
          { match: { artist: { query: query, boost: 5 } }},
          { match: { lyrics: query }},
        ],
      },
    },
    highlight: {
      fields: {
        title: {},
        artist: {},
        lyrics: {}
      }
    }
  }
  self.__elasticsearch__.search(params)
end

নতুন highlight ফিল্ড নির্দিষ্ট করে কোন ফিল্ডগুলো হাইলাইট করা উচিত। আমরা সকল ফিল্ড সিলেক্ট করলাম। এখন, https://localhost:3000/query=genesis লোড করলে, আপনি একটি নতুন ফিল্ড দেখবেন যেটি "highlight" নামে থাকবে যেটিতে ডকুমেন্ট ফিল্ডগুলো থাকবে ম্যাচ করা ফ্রেজ em ট্যাগে র‍্যাপ করে।

হাইলাইটিং সম্পর্কে আরো জানার জন্য অফিসিয়াল গাইড দেখুন।

Fuzziness (অনিশ্চয়তা)

ঠিক আছে, যদি আমরা ভুলে benesis লিখি genesis বদলে? এটি কোনো রেজাল্ট রিটার্ন করবে না, কিন্তু আমরা ইলাস্টিকসার্চকে বলতে পারি কম চুনা করুন এবং ফাজি সার্চ (fuzzy search) অ্যালো করুন, যাতে genesis রেজাল্টও দেখায়।

এটি কীভাবে করা যায়: শুধু artist কোয়েরি পরিবর্তন করুন { match: { artist: { query: query, boost: 5 } }} থেকে { match: { artist: { query: query, boost: 5, fuzziness: "AUTO" } }}। সঠিক ফাজিনেস মেকানিক্স কনফিগার করা যায়। বিস্তারিতের জন্য অফিসিয়াল ডক্স দেখুন।

এখন কী করবে?

আশা করি এই আর্টিকেল আপনাকে আশ্বস্ত করল যে ইলাস্টিকসার্চ একটি শক্তিশালী টুল যা ব্যবহার করা উচিত যখন আপনাকে নন-ট্রivial সার্চ ইম্প্লিমেন্ট করতে হবে। আরও শিখতে চাইলে কিছু হেল্পফুল লিংক:

Resources

  • অফিসিয়াল ইলাস্টিকসার্চ রেফারেন্স
  • Ruby জেম
  • Rails জেম
  • ব্যবহারিক জ্ঞান سے ভরা একটি খুব ভালো বই
  • অটোকমপ্লিট তৈরি করা

Alternative gems

  • Searchkick
  • Chewy
  1. স্ট্রাইপ চেকআউট (Stripe Checkout) দিয়ে রেইলসে সিমলেস ওয়ান-টাইম পারচেজ ইন্টিগ্রেশন

  2. Hotwire দিয়ে Rails অ্যাপস দ্রুত করুন: JavaScript ছাড়া সার্ভার-সাইড রেন্ডারিং

  3. রুবি অন রেইলসে টেইলউইন্ড CSS যোগ করা: একটি প্র্যাকটিক্যাল ধাপে ধাপে গাইড

  4. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি