我正在尝试在我的Rails 5项目中使用ThinkingSphinx。我在http://freelancing-gods.com/thinking-sphinx/
读了一条指令我需要在SQL支持的索引上实现OR
逻辑。
这是我的班级:
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
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个索引 - :sender_email
和:recipient_email
- 但忽略indexes text
。
在伪代码中我需要这样的东西:
Message.search 'manager1@example.com' :conditions => {:sender_email => 'client1@example.com' OR :receiver_email => 'client1@example.com'}
这意味着:找到'manager1@example.com'和'client1@example.com'之间的所有消息(每个消息可以是发件人或接收者) - 忽略包含带有'manager1'字样的文本的消息@ example.com'或'client1@example.com'。
不幸的是,文档说:
The :conditions option must be a hash, with each key a field and each value a string.
换句话说,我需要一个条件索引集(在运行时) - 但同时需要超过2个索引(不记录为1)。
我的意思是,只允许哈希作为条件是一个坏主意 - 而且没有字符串(比如ActiveRecord查询允许http://guides.rubyonrails.org/active_record_querying.html#pure-string-conditions)。
PS我会说ThinkingSphinx文档http://freelancing-gods.com/thinking-sphinx/非常糟糕,需要从头开始重写。我读了这一切,什么都不懂。它没有例子(完整的例子 - 只有部分 - 因此完全不清楚)。我甚至不明白什么是字段和属性,它们有什么不同。协会,条件等 - 都不清楚。很坏。宝石本身看起来很不错 - 但它的文档非常糟糕。
答案 0 :(得分:0)
我很遗憾听到您在文档中找不到适合您的解决方案。 Sphinx面临的挑战是它使用SphinxQL语法,它与SQL非常相似,但有时也非常不同 - 因此人们通常会期望类似SQL的行为。
这也是维护这个宝石的挑战的一部分 - 我不确定过于模仿ActiveRecord语法是否明智,否则可能会让事情变得更加混乱。
这里要注意的关键是你可以利用Sphinx的extended query syntax进行比赛,以获得你之后的行为:
Message.search :conditions => {
:sender_email => "(client1@example.com | manager1@example.com)",
:receiver_email => "(client1@example.com | manager1@example.com)"
}
这将返回发件人是两个值之一的任何内容,和接收者是两个值中的任何一个。当然,这个将包含从client1发送到client1,或者manager1发送到manager1的任何消息,但是我希望这种消息很少见,也许不是那么大的问题。
需要注意的一点是,@
和.
通常不会被视为可搜索的字词,因此您可能需要add them to your charset_table。
此外,鉴于您实际上对数据库列的整个值执行完全匹配,这确实感觉就像一个查询实际上更好地服务于列上的某些数据库索引并使用SQL代替。 Sphinx(我说大多数/所有其他全文搜索库)最适合在较大的文本字段中匹配单词和短语。
至于文档......我已经付出了很多努力来努力使它们变得有用,尽管我意识到仍然可以进行很多改进。我确实有一个概述how fields and attributes differ的页面 - 如果不清楚,绝对欢迎提供反馈。
保持文档最新需要在小型和新项目中付出很多努力 - 而Thinking Sphinx既不是这些,也不是几个月内的10年。我对它如何运作良好感到自豪,它仍然支持最新版本的Rails,并且它仍然得到积极维护和支持。但它是开源的 - 它在我(和其他人的)业余时间里完成了。它并不完美。如果您想方设法改进,请做出贡献!代码和文档都在GitHub上,拉取请求非常受欢迎。