简体   繁体   English

如何使用pg_search搜索对象的虚拟属性?

[英]How do I search against an object's virtual attribute with pg_search?

I have a class Node that I have setup acts_as_taggable on, so I can add user_tags to any node. 我有一个类Node我已经设置了acts_as_taggable ,所以我可以将user_tags添加到任何节点。 I also have a method on my Node model that will look up the actual User records for all the users in the user_tag_list . 我的Node模型上还有一个方法,它将查找user_tag_list所有用户的实际User记录。 Here is an illustration: 这是一个例子:

[32] pry(main)> m = Node.find(85)
  Node Load (8.6ms)  SELECT  "nodes".* FROM "nodes"  WHERE "nodes"."id" = $1 LIMIT 1  [["id", 85]]
=> #<Node id: 85, name: "House Fire 2", family_tree_id: 57, user_id: 57, media_id: 228, media_type: "Video", created_at: "2015-05-15 00:20:26", updated_at: "2015-05-20 01:06:34">
[33] pry(main)> m.user_tags
  ActsAsTaggableOn::Tag Load (3.8ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."context" = 'user_tags'  [["taggable_id", 85], ["taggable_type", "Node"]]
=> [#<ActsAsTaggableOn::Tag id: 4, name: "gerry@test.com", taggings_count: 1>, #<ActsAsTaggableOn::Tag id: 6, name: "danny@test.com", taggings_count: 1>]
[34] pry(main)> m.user_tag_list
  ActsAsTaggableOn::Tag Load (0.8ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'user_tags' AND taggings.tagger_id IS NULL)  [["taggable_id", 85], ["taggable_type", "Node"]]
=> ["gerry@test.com", "danny@test.com"]
[35] pry(main)> m.tagged_users
  User Load (5.7ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'gerry@test.com' LIMIT 1
  User Load (2.1ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'danny@test.com' LIMIT 1
=> [#<User id: 52, email: "gerry@test.com", encrypted_password: "$2a$10$KaX1kvtIw1.jGITnt9Czqeq3xTzhY3OM052NSHsL5Lf...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 5, current_sign_in_at: "2015-04-03 17:10:28", last_sign_in_at: "2015-04-03 00:38:24", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-03-05 01:36:31", updated_at: "2015-04-03 17:10:28", first_name: "Gerry ", confirmation_token: nil, confirmed_at: "2015-03-05 01:36:52", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "uncle", avatar: nil, invitation_token: nil, invitation_created_at: "2015-03-05 01:36:31", invitation_sent_at: "2015-03-05 01:36:31", invitation_accepted_at: "2015-03-05 01:36:52", invitation_limit: nil, invited_by_id: 1, invited_by_type: "User", invitations_count: 0, bio: nil, last_name: "Atrick", gender: 0>,
 #<User id: 58, email: "danny@test.com", encrypted_password: "$2a$10$ZpzLH17iFrOXzH4U/pOX.e4nwN.9IJ1s1Ap/zQglk9K...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 6, current_sign_in_at: "2015-05-26 04:36:32", last_sign_in_at: "2015-04-03 00:14:55", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-03-12 03:39:28", updated_at: "2015-05-26 04:36:32", first_name: "Daniel", confirmation_token: nil, confirmed_at: "2015-03-12 05:46:18", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "son", avatar: nil, invitation_token: nil, invitation_created_at: "2015-03-12 03:39:28", invitation_sent_at: "2015-03-12 03:39:28", invitation_accepted_at: "2015-03-12 05:46:18", invitation_limit: nil, invited_by_id: 57, invited_by_type: "User", invitations_count: 0, bio: nil, last_name: "Marty", gender: 0>]

So, ideally, what I would like to do is allow users to search for say Gerry and it would return Node.id = 85 from the above example, because Node.id = 85 has a user tag with the first name Gerry . 因此,理想情况下,我想要做的是允许用户搜索说Gerry ,它会从上面的示例返回Node.id = 85 ,因为Node.id = 85有一个名为Gerry的用户标签。

This is my existing pg_search on Node : 这是我在Node上的现有pg_search

  pg_search_scope :node_search, against: [:name, :user_id, :circa],
    using: { tsearch: { any_word: true} },
    :associated_against => {
      comments: [:message],
      user: [:first_name, :last_name, :email],
      memberships: [:relation]
    }

I feel like I should be able to use pg_search's dynamic scope, but I can't quite grok it. 我觉得我应该能够使用pg_search的动态范围,但我不能理解它。

How would I achieve this? 我怎么做到这一点?

It turns out that the answer is pretty straight-forward. 事实证明,答案非常简单。

Given that this is the declaration of acts-as-taggable-on in my Node model: 鉴于这是我的Node模型中acts-as-taggable-on的声明:

acts_as_taggable_on :user_tags

The solution is simply to add this column in the pg_search declaration like so: 解决方案只是在pg_search声明中添加此列,如下pg_search

  include PgSearch
  pg_search_scope :node_search, against: [:name, :user_id, :circa],
    using: { tsearch: { any_word: true, dictionary: :english} },
    :associated_against => {
      comments: [:message],
      user: [:first_name, :last_name, :email],
      memberships: [:relation],
      user_tags: [:name]
    }

Note that I had to specify the field within user_tags (ie the :name attribute). 请注意,我必须在user_tags指定字段(即:name属性)。

So now, it searches against that virtual attribute of :user_tags like I wanted. 所以现在,它会搜索我想要的虚拟属性:user_tags

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM