0

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

アカウントごとに個別のインデックスがあり、各モデル (ユーザーとコメント - 実際のアプリには多くのモデルがある例) のマッピングが指定されています。この場合、ユーザー モデルまたはコメント モデルに変更が加えられた場合、関連するアカウント用に作成されたインデックスを更新する必要があります。これは可能ですか?はいの場合はお知らせください。

私の場合、これがマッピングを指定する方法だと思います。私が間違っている場合は修正してください。

アカウント モデル:

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

インデックスは、アカウント インデックスの両方のマッピングで正しく作成されています。しかし、マッピングで指定されたモデルが変更されたときにインデックスを更新する方法がわかりません。

新しいユーザーが追加されるか、ユーザーが更新されるたびに、対応するアカウント用に作成されたインデックスを更新する必要があります。

4

2 に答える 2

3

この質問は、Github issue Multiple model single index approachからクロスポストされています。ここで答えをクロスポストします。


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 ではなく、時間に基づいてデータをスライスします。

http://localhost:9200/_aliases?pretty非常に単純化された curl出力から始めて、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 エイリアスに対してインデックスを作成します。どのコンポーネントが検索されていても、特定のコンポーネントにとって意味のあるエイリアスまたはインデックスに対して検索します。

于 2012-12-12T20:54:02.543 に答える
0

おそらく、rubberband https://github.com/grantr/rubberbandのような別の宝石を使用して、必要に応じてインデックスを設定することをお勧めします。

次に、 User および Comment モデルをマッピングする際に、Tire を使用して次のようなことを行うことができます。

tire.mapping :_routing => { :required => true, :path => :account_id } do
  index_name 'account_name_here'
  ...
  ...
end

注意が必要な部分は、account_id または名前をその index_name 文字列/引数に取得することです。簡単または難しい場合があります。index_name を動的に割り当てることはまだ試していません。

お役に立てれば!

于 2012-12-08T08:23:39.370 に答える