2017-06-05 51 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