Hi Robert

Good to see you spotted the docs on CRC'ing string attributes.

Unfortunately, when you add a filter, it needs to apply to all indexes. As a 
work-around, you could add an integer (or CRC'd string, if you really want) as 
the attribute to all other indexed models - and then include that when 
filtering:

  has '0', :as => :search_access_tag, :type => :integer

  ThinkingSphinx.search :with => {:search_access_tag => (access_tags.collect { 
|tag| tag.to_crc32 } + 0)}

I think that should work - the only problem is if any of your access tags are 
blank (which I'm pretty sure is CRC'd to 0). Sphinx doesn't have the concept of 
signed integers, though, so 0 or 1 or something small is best.

Cheers

-- 
Pat

On 30/06/2010, at 2:30 AM, rbjarnason wrote:

> Hi,
> 
> Ok, didn't read enough of the manual...  It was due to not using
> CRC32.  Seems to be working now except for passing an empty array to
> the :with but I can work around that by using a random string that
> will never be a real find.
> 
> One final question, when using ThinkingSphinx.search and :with can I
> conditions the :with parameter only to apply to the Projects table?  I
> have a couple of other tables that are searchable and they do not have
> the search_access_tag field and they don't seem to showing up anymore.
> 
> Warm regards,
> Robert
> 
> On Jun 29, 5:11 pm, rbjarnason <[email protected]> wrote:
>> Hi Pat,
>> 
>> I've now implemented a solution, not sure if this is the best way but
>> it seems to work pretty well.
>> 
>> I added a new field to the projects table called search_access_tag,
>> this is a string field that has the following structure
>> "#{project_type_id}-#{client_id}", then I make sure this is created
>> after save each time.
>> 
>> Then add it to the ts index as:
>> has search_access_tag
>> 
>> Then in the search I do:
>> access_tags = ProjectAccess.find(:all, :conditions => {:user_id =>
>> current_user.id}).collect { |access| access.search_access_tag } #
>> Where the identical string access_tags are created from the
>> project_type_id and client_id for that user
>> @search_results = ThinkingSphinx.search params[:search], :page =>
>> params[:page], :retry_stale => true, :order
>> => :created_at,  :sort_mode
>> => :desc, :with=>{:search_access_tag=>access_tags}
>> 
>> This all works roughly as expected and seems to be fast.
>> 
>> Until I try this for testing I have a problem:
>> 
>> 1. access_tags = [] # Empty, hoping for 0 results
>> @search_results = ThinkingSphinx.search params[:search], :page =>
>> params[:page], :retry_stale => true, :order
>> => :created_at,  :sort_mode
>> => :desc, :with=>{:search_access_tag=>access_tags}
>> 
>> This seems to disables the access filtering and all projects are
>> returned - I would have expected no projects to be returned.
>> 
>> 2. access_tags = ["CJNFDHJH"] # Random nonsense to try to get 0
>> returns
>> @search_results = ThinkingSphinx.search params[:search], :page =>
>> params[:page], :retry_stale => true, :order
>> => :created_at,  :sort_mode
>> => :desc, :with=>{:search_access_tag=>access_tags}
>> 
>> This returns 5 projects all from the same project type.  I've checked
>> and there seems to be nothing special about this one project type.
>> 
>> I would have thought that has and with on a string would be an exact
>> string match so if the string is not found in the :with array it would
>> not return any results.
>> 
>> From the ts generated config, here are the bits related to
>> search_access_tag:
>> 
>> sql_query = .... IFNULL(`projects`.`search_access_tag`, '') AS
>> `search_access_tag` ....
>> sql_attr_str2ordinal = search_access_tag
>> 
>> Any ideas?
>> 
>> Warm regards,
>> Robert
>> 
>> On Jun 29, 8:38 am, rbjarnason <[email protected]> wrote:
>> 
>> 
>> 
>>> Hi Pat,
>> 
>>> Thanks for a quick answer :)
>> 
>>> Couple of follow up points.
>> 
>>> With a theoretical limit of about 2500 users and few hundred
>>> projects.  Would the former approach be possible/practical/workable?
>> 
>>> Reason I'm asking is that we're being asked if it would be possible to
>>> add another layer of access control where each project would both have
>>> a project type and a client id and the ProjectAccess would then have
>>> (project_type_id, client_id, user_id).
>> 
>>> I guess it would be simpler to collect the user_ids in the index for
>>> each project with that extra access dimension.
>> 
>>> Our access filter would look something like this:
>>>   named_scope :filtered, lambda {{ :joins=>"INNER JOIN project_access
>>> ON project_access.project_type_id = projects.project_type_id AND \
>> 
>>> project_access.client_id = projects.client_id",
>>>                                                   :conditions =>
>>> ["project_access.user_id = ?", Thread.current[:user_id]] }}
>> 
>>> I noticed that you've recently added a :join option to the code, which
>>> I gathered could be used in this case to collect the ids for the
>>> index, do you have any example snippets for using this feature?
>> 
>>> Or would it be possible somehow to combine the project_type_id and
>>> client_id in the second approach and search :with a combination of the
>>> two?
>> 
>>> Warm regards,
>>> Robert
>> 
>>> On Jun 29, 4:44 am, Pat Allan <[email protected]> wrote:
>> 
>>>> Hi Robert
>> 
>>>> I guess there's two approaches here... you'll either want to store all the 
>>>> user ids that have access to a given project:
>> 
>>>>   has project_type.project_accesses.user_id, :as => :user_ids
>> 
>>>> However, if you're going to have a lot of users, this may not be the best 
>>>> approach... I would recommend you store the project type id as an 
>>>> attribute instead:
>> 
>>>>   has project_type_id
>> 
>>>> Then, find out which project types a user has access to:
>> 
>>>>   project_type_ids = ProjectAccess.find(:all, :conditions => {:user_id => 
>>>> current_user.id}).collect { |access| access.project_type_id }
>> 
>>>> And use that as a filter in the search:
>> 
>>>>   Project.search 'foo', :with => {:project_type_id => project_type_ids}
>> 
>>>> Hope this helps.
>> 
>>>> --
>>>> Pat
>> 
>>>> On 29/06/2010, at 11:55 AM, rbjarnason wrote:
>> 
>>>>> Hi,
>> 
>>>>> I'm trying to implement search using Thinking Sphinx for Projects that
>>>>> have access control based on Project Types.
>> 
>>>>> I have 4 tables I need to work with:
>>>>> * Project (included in search)
>>>>> * Project Type (included by association in search)
>>>>> * User (the logged in user)
>>>>> * Project Access (which has project_type_id, user_id)
>> 
>>>>> When logged in, I would only like to return search results for
>>>>> projects of types that a given user has access to as defined in the
>>>>> Project Access table.
>> 
>>>>> I've been looking at this post: "Limiting search results depending on
>>>>> authorization level" that has given me few clues but I'm still at a
>>>>> loss how I begin implementing this sort of access control using
>>>>> Thinking Sphinx.
>>>>> http://groups.google.com/group/thinking-sphinx/browse_thread/thread/4...
>> 
>>>>> Any leads would be highly appreciated.
>> 
>>>>> Warm regards,
>>>>> Robert Bjarnason
>> 
>>>>> --
>>>>> You received this message because you are subscribed to the Google Groups 
>>>>> "Thinking Sphinx" group.
>>>>> To post to this group, send email to [email protected].
>>>>> To unsubscribe from this group, send email to 
>>>>> [email protected].
>>>>> For more options, visit this group 
>>>>> athttp://groups.google.com/group/thinking-sphinx?hl=en.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Thinking Sphinx" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/thinking-sphinx?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Thinking Sphinx" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/thinking-sphinx?hl=en.

Reply via email to