1

私のマルチテナント アプリ (アカウントごとのユーザー数に基づくアカウント) では、ユーザー ドキュメントが変更されたときに特定のアカウントのインデックスをどのように更新しますか。

Tire gem を介して Elasticsearch を使用します。

Rails 2.3 アプリ - loe/tire のコミットに従って、Rails 2.3 のサポートを有効にするための変更を適用しました

アカウント モデル:

  include Tire::Model::Search

  Tire.index('account_1') do
    create(
      :mappings => {
        :user => {
          :properties => {
            :name => { :type => :string, :boost => 10 },
            :company_name => { :type => :string, :boost => 5 }
          }
        },
        :comments => {
          :properties => {
            :description => { :type => :string, :boost => 5 }
          }
        }
      }
    )
  end

上記のように、ここにはユーザーとコメントの 2 つのモデルがあります。複数のモデルで単一のインデックスに対処する正しい方法ですか。

その場合、ユーザー ドキュメントまたはコメント ドキュメントだけが変更されたときにインデックスを更新するにはどうすればよいですか?

4

2 に答える 2

0

タイヤ所有者Karmiが投稿した質問に対する回答は次のとおりです。

Account クラスがあり、記事エンティティを扱っているとします。

その場合、Account クラスは次のようになります。

class Account
  #...

  # Set index name based on account ID
  #
  def articles
      Article.index_name "articles-#{self.id}"
      Article
  end
end

したがって、特定のアカウントの記事にアクセスする必要があるときはいつでも、検索またはインデックス作成のために、次のように簡単に実行できます。

@account = Account.find( remember_token_or_something_like_that )

# Instead of `Article.search(...)`:
@account.articles.search { query { string 'something interesting' } }

# Instead of `Article.create(...)`:
@account.articles.create id: 'abc123', title: 'Another interesting article!', ...

ユーザー/アカウントごとに個別のインデックスを持つことは、特定のケースでは完璧に機能しますが、数万または数十万 (またはそれ以上) のインデックスがある場合には、うまくいきません。この場合、適切に設定されたフィルターとルーティングを使用してインデックス エイリアスを使用すると、パフォーマンスが大幅に向上します。テナント ID ではなく、時間に基づいてデータをスライスします。

非常に単純化された curl http://localhost:9200/_aliases?pretty出力から始めて、2 番目のシナリオを見てみましょう。

{
  "articles_2012-07-02" : {
    "aliases" : {
      "articles_plan_pro" : {
      }
    }
  },
  "articles_2012-07-09" : {
    "aliases" : {
      "articles_current" : {
      },
      "articles_shared" : {
      },
      "articles_plan_basic" : {
      },
      "articles_plan_pro" : {
      }
    }
  },
  "articles_2012-07-16" : {
    "aliases" : {
    }
  }
}

週に 1 つずつ、3 つのインデックスがあることがわかります。article_plan_pro と article_plan_basic という 2 つの類似したエイリアスがあることがわかります。明らかに、「pro」サブスクリプションのアカウントは 2 週間前を検索できますが、「basic」サブスクリプションのアカウントは今週しか検索できません。

また、articles_current エイリアスが現在の週を指していることにも注意してください (これを書いているのは 2012 年 7 月 12 日木曜日です)。来週のインデックスはちょうどそこにあり、配置して待っています。時が来れば、バックグラウンド ジョブ (cron、Resque ワーカー、カスタム スクリプトなど) がエイリアスを更新します。Tire 統合テスト スイートには、「スライディング ウィンドウ」シナリオでエイリアスを使用した気の利いた例があります。

ここでは、articles_shared エイリアスを見てみましょう。この設定でどのようなトリックを実行できるかを見てみましょう。

class Account
  # ...

  # Set index name based on account subscription
  #
  def articles
    if plan_code = self.subscription && self.subscription.plan_code
      Article.index_name "articles_plan_#{plan_code}"
    else
      Article.index_name "articles_shared"
    end
    return Article
  end
end

ここでも、ドキュメントを保持する Article クラスの index_name を設定しています。現在のアカウントに有効なサブスクリプションがある場合、サブスクリプションから plan_code を取得し、このアカウントの検索を関連するインデックス (「basic」または「pro」) に向けます。

アカウントがサブスクリプションを持っていない場合 (彼はおそらく「訪問者」タイプです)、検索を article_shared エイリアスに向けます。インターフェイスの使用は以前と同じくらい簡単です。ArticlesController:

@account  = Account.find( remember_token_or_something_like_that )
@articles = @account.articles.search { query { ... } }
# ...

この場合、インデックス作成のゲートウェイとして Article クラスを使用していません。別のインデックス作成コンポーネント、elasticsearch Bulk API へのライト プロキシとして機能する Sinatra アプリケーションがあり、HTTP 認証、ドキュメントの検証 (必要なプロパティや UTC として渡された日付などのルールの適用) を提供し、裸の Tire::Index#import を使用します。および Tire::Index#store API。

これらの API は、上記のバックグラウンド プロセスで現在の週に定期的に更新される article_currentindex エイリアスと通信します。このようにして、アプリケーションの個別のコンポーネントでインデックス名を設定するためのすべてのロジックを切り離したので、インデックス プロキシ (別のサーバーで実行されます) の Article または Account クラスへのアクセスは必要ありません。アプリケーションのコンポーネント。どのコンポーネントがインデックスを作成していても、articles_current エイリアスに対してインデックスを作成します。どのコンポーネントが検索されていても、特定のコンポーネントにとって意味のあるエイリアスまたはインデックスに対して検索します。

于 2013-01-03T11:41:24.433 に答える
0

通常、モデルにインデックスを付ける場合は、自己属性とその関連にインデックスを付けるとよいでしょう。したがって、この場合、ユーザーとそのコメントにインデックスを付ける必要がある場合は、ユーザー モデルにインデックスを作成し、関連付けによって参照されるコメントにインデックスを付けて、ユーザー モデルにコールバックが適用され、モデルに属性がある場合はユーザー オブジェクトを再インデックス化する必要があります。変更されます。これは、インデックスがあるモデルのみです。

関連付けにインデックスを付けたい場合は、ユーザー/コメントモデルの保存後/破棄後にアカウントオブジェクトにインデックスを付けるフックが必要です。または、:touch => true オプションを使用して、ユーザー/コメントの変更時にアカウント モデルに触れることもできます。

例: index ユーザーとコメントが必要な場合、

  include Tire::Model::Search
  include Tire::Model::Callbacks

     mapping do
        indexes :id,                  :type => 'integer', :index    => :not_analyzed
        indexes :about_me,            :type => 'string',  :index    => :snowball
        indexes :name,                :type => 'string',  :index    => :whitespace

        indexes :comments do
          indexes :content,                  :type => 'string', :analyzer => 'snowball'
        end
    end

したがって、ここではインデックスはユーザー モデルにあり、user.comments は関連付けです。この例で説明できることを願っています

于 2012-11-14T07:00:34.390 に答える