2

I have a class Post, with the following scope:

scope :by_tag, ->(tag){ where(:desc => /##{Regexp.escape(tag)}/) }

It works very well with one tags, but I can't make it work with various tags.

For example: I cant make it give me the posts tagged with #rails AND #regexp.

With criteria union I can make it return me the posts tagged with #rails OR #regexp.

How can I get it to work? I'm using mongoid, btw.

Thanks in advance.


Just fount that is not an OR. What happens is that the second time I call by_tag, it overrides the previous. I believe that's because it's the same property.

Someone know how to fix this? Thanks

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
caarlos0
  • 20,020
  • 27
  • 85
  • 160

1 Answers1

1

Regexp queries tend to be really slow. Instead, store an array of tags and use $in to query the array.

With Mongoid 2.x use all_in

scope :by_tags, ->(*tags) { all_in(tags: *tags) }

With Mongoid 3 use all merge strategy

scope :by_tags, ->(*tags) { all(tags: *tags) }
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • very interesting. I'll try it at home tonight. Thank you very much! – caarlos0 Oct 17 '12 at 11:51
  • by the way: I can pass a array of tags, and it will automatically find the items that contains all tags passed? Ex: `Post.by_tags '#mongo', '#rails'` will return me the item Post with desc= 'testing #mongo in #rails'? That easy? – caarlos0 Oct 17 '12 at 11:55
  • No, the desc field must be stored as array. If you want to keep the desc field as string like it is, add a new field (e.g. tags) that you set when storing the desc that contains the list of tags extracted from the desc. Then, you'll be able to query it with `by_tags` – Simone Carletti Oct 17 '12 at 11:57
  • got that... I'll have to do that anyway to made my life a bit easier in other places of the app. thanks man, at night I give you some feedback. – caarlos0 Oct 17 '12 at 12:03