2017-06-05 52 views
0

我想在我的Rails 5項目中使用ThinkingSphinx(帶有SQL支持的索引)。ThinkingSphinx:SQL支持索引上的動態索引?

我需要一些動態運行時索引來搜索。

我有一個Message模型:

class Message < ApplicationRecord 
    belongs_to :sender, class_name: 'User', :inverse_of => :messages 
    belongs_to :recipient, class_name: 'User', :inverse_of => :messages 
end 

及其索引:

ThinkingSphinx::Index.define :message, :with => :active_record, :delta => true do 
    indexes text 

    indexes sender.email, :as => :sender_email, :sortable => true 

    indexes recipient.email, :as => :recipient_email, :sortable => true 

    indexes [sender.email, recipient.email], :as => :messager_email, :sortable => true 

    has sender_id, created_at, updated_at 

    has recipient_id 

end 

schema.rb:

create_table "messages", force: :cascade do |t| 
    t.integer "sender_id" 
    t.integer "recipient_id" 
    t.text  "text" 
    t.datetime "created_at",     null: false 
    t.datetime "updated_at",     null: false 
    t.boolean "read",   default: false 
    t.boolean "spam",   default: false 
    t.boolean "delta",  default: true, null: false 
    t.index ["recipient_id"], name: "index_messages_on_recipient_id", using: :btree 
    t.index ["sender_id"], name: "index_messages_on_sender_id", using: :btree 
    end 

問題是關於所謂的 「對話」。它們不存在於數據庫中 - 它們是在運行時確定的。對話框 - 這是2個用戶之間的一組消息,每個用戶可能是發送者或接收者。

任務是搜索我的對話框,並通過通訊錄電子郵件找到對話框(對話框的消息)。太複雜了!

這裏是我的努力:

conditions = {messager_email: search_email} 

    with_current_user_dialogs = 

    "*, IF(sender_id = #{current_user.id} OR recipient_id = #{current_user.id}, 1, 0) AS current_user_dialogs" 

    messages = Message.search search_email, conditions: conditions, 

    select: with_current_user_dialogs, 
    with: {'current_user_dialogs' => 1} 

這幾乎是罰款 - 但仍然沒有。此查詢僅在我的對話框(在我發送或接收的消息內)內正確搜索,並且僅在:sender:recipient字段中同時發生(這不是最佳的)。

說我的電子郵件是「[email protected]」。其他電子郵件如「[email protected]」,「[email protected]」,「[email protected]」。

麻煩的是,當我搜索「client1」時 - 我收到了我是發件人或收件人的所有消息。但我不應該得到任何迴應 - 我只需要在我的記者電子郵件中搜索 - 而不是我的。

甚至在查詢「客戶端」時也會發生更糟糕的事情 - 我通過「[email protected]」,「[email protected]」取回正確的通訊記錄,但結果被錯誤地改爲「client1 @ example」。 COM」。

我需要一種方法來在運行時選擇 - 在哪個索引子集中進行搜索。

我的意思是這個條件是不夠的,我說:

indexes [sender.email, recipient.email], :as => :messager_email, :sortable => true 

它搜索(對於「客戶」)內所有的sender.email和所有的recipient.email一次。

但我需要動態地選擇,如:「搜索sender.email值符合if sender.id != current_user.id」或「搜索recipient.email符合if recipient.id != current_user.id」(因爲我可以作爲一個發送者作爲接收器)。

這就是我所說的「動態指數」。

如何做到這一點?這樣的「動態指標」肯定取決於當前的價值 - 所以即使在相同的總消息集中,不同用戶也會有所不同。

很明顯,我不能申請任何後搜索截止(什麼切斷?) - 我需要以某種方式限制搜索本身。

我試圖搜索一些範圍 - 但得到的錯誤是「搜索範圍不可能」 - 類似的東西。

也許我應該使用實時索引而不是SQL支持索引?

對不起我的問題的複雜性。

回答

1

以下工作?

other = User.find_by :email => search_email 
with_current_user_dialogs = "*, IF((sender_id = #{current_user.id} AND recipient_id = #{other.id}) OR (recipient_id = #{current_user.id} AND sender_id = #{other.id}), 1, 0) AS current_user_dialogs" 

或者您需要在搜索到的電子郵件地址中進行部分匹配嗎?

[編輯]

好了,從下面的評論的討論,很明顯,現場數據是至關重要的。雖然可以構建同時使用字段和屬性的搜索查詢,但在查詢中不能包含組合這兩者的邏輯。也就是說,你不能說:「當'i'屬性爲1時搜索字段'x',否則搜索字段'y'。」

我可能看到這個工作的唯一方法是如果你使用字段的兩個部分的邏輯。也許像下面這樣:

+0

我需要一個「實時搜索」 - 當用戶輸入一個搜索詞(逐個字母)時,搜索結果會立即縮小。所以我需要一個搜索引擎 - 只需ActiveRecord是不夠的。 – prograils

+0

我可以有一些模型帶有實時索引,並且一些帶有SQL支持索引**嗎?那麼我應該如何應用 - 'rake ts:regenerate'或'rake ts:rebuild'? – prograils

+0

恐怕,您目前無法混合使用SQL支持的索引和實時支持的索引。 – pat