2017-05-30 2 views
0

J'essaie d'utiliser ThinkingSphinx dans mon projet Rails 5. J'ai lu une instruction à http://freelancing-gods.com/thinking-sphinx/ThinkingSphinx: condition-OR sur les index SQL?

J'ai besoin d'implémenter la logique OR sur les index SQL.

Voici ma classe:

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

et son indexeur:

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 

donc je dois rechercher uniquement dans les 2 indices à une fois - :sender_email et :recipient_email - mais ignorin g indexes text.

En pseudocode je besoin de quelque chose comme ceci:

Message.search '[email protected]' :conditions => {:sender_email => '[email protected]' OR :receiver_email => '[email protected]'} 

Ce qui signifie: trouver tous les messages entre « [email protected] » et « [email protected] » (chacun d'entre eux pourrait être un expéditeur ou un destinataire) - en ignorant les messages contenant le texte avec les mots «[email protected]» ou «[email protected]».

Malheureusement, les docs disent:

The :conditions option must be a hash, with each key a field and each value a string. 

En d'autres termes, je besoin d'un ensemble d'indices sous condition (à l'exécution) - mais en même temps plus de 2 indices (non 1 comme documenté).

Je veux dire que c'est une mauvaise idée de ne permettre que des hachages comme condition - et aucune chaîne (comme les requêtes ActiveRecord permettent http://guides.rubyonrails.org/active_record_querying.html#pure-string-conditions). PS Je dirais que la documentation de ThinkingSphinx http://freelancing-gods.com/thinking-sphinx/ est plutôt mauvaise et doit être entièrement réécrite. J'ai tout lu et n'ai rien compris. Il n'a pas d'exemples (exemples complets - seulement partiel - donc totalement flou). Je ne comprends même pas ce que sont les champs et les attributs et comment ils diffèrent. Associations, conditions, etc. - tout n'est pas clair. Très mauvais. La gemme elle-même semble plutôt bien - mais sa documentation est horrible.

Répondre

0

Nous sommes désolés d'apprendre que vous n'avez pas trouvé de solution qui vous convient dans la documentation. Ce qui est difficile avec Sphinx, c'est qu'il utilise la syntaxe SphinxQL, qui est très similaire à SQL, mais aussi très différente à certains moments - et les gens s'attendent souvent à un comportement similaire à SQL.

Cela fait aussi partie du défi de maintenir cette gemme - je ne suis pas sûr qu'il est sage d'imiter la syntaxe ActiveRecord de trop près, sinon cela pourrait rendre les choses plus confuses.

L'essentiel à noter ici est que vous pouvez utiliser Sphinx de extended query syntax pour les matchs pour obtenir le comportement que vous êtes après:

Message.search :conditions => { 
    :sender_email => "([email protected] | [email protected])", 
    :receiver_email => "([email protected] | [email protected])" 
} 

Cela renverra quoi que ce soit lorsque l'expéditeur est l'une des deux valeurs , et le récepteur est l'une des deux valeurs.Bien sûr, ce inclura tous les messages envoyés de client1 à client1, ou manager1 à manager1, mais je m'attendrais à ce que ce soit rare et peut-être pas un gros problème. Il est à noter queet . ne sont généralement pas traités comme des caractères de recherche, donc vous devrez peut-être add them to your charset_table. En outre, étant donné que vous effectuez réellement des correspondances exactes sur l'ensemble des valeurs des colonnes de base de données, cela semble être une requête mieux servie par certains index de base de données sur les colonnes et utilisant SQL à la place. Sphinx (et je dirais que la plupart/toutes les autres bibliothèques de recherche en texte intégral) sont les mieux adaptés pour faire correspondre des mots et des phrases dans des champs de texte plus grands. En ce qui concerne la documentation ... J'ai déployé beaucoup d'efforts pour essayer de les rendre utiles, même si je me rends compte qu'il y a encore beaucoup d'améliorations qui pourraient avoir lieu. J'ai une page qui décrit how fields and attributes differ - si ce n'est pas clair, les commentaires sont les bienvenus.

Garder la documentation à jour demande beaucoup d'efforts dans les petits et nouveaux projets - et Thinking Sphinx n'est ni l'un ni l'autre, ayant 10 ans dans quelques mois. Je suis fier de la façon dont il fonctionne encore bien, il prend toujours en charge les dernières versions de Rails, et il est toujours activement maintenu et pris en charge. Mais c'est open source - c'est fait dans mon temps libre (et celui des autres). Ce n'est pas parfait. Si vous trouvez des moyens d'améliorer les choses, n'hésitez pas à contribuer! Le code et les docs sont sur GitHub, et les requêtes pull sont les bienvenues.