如何在Mongoid中嵌套.or()和.and()条件

时间:2014-01-24 07:27:35

标签: mongodb mongoid mongoid3

我有一个'搜索'功能,我希望传递一个任意'过滤'条件并返回匹配

以下内容匹配过滤字符串匹配的任何名称/电子邮件:

@people = Person.all
@people = @people.or(
    {'name.first_name' => /#{filter}/i}, 
    {'name.last_name' => /#{filter}/i}, 
    {'email' => /#{filter}/i }
)

以下在Person记录的'tags'数组中正确执行相同的操作:

@people = Person.all
@people = @people.any_in('tags' => [/#{filter}/i])

任何人都可以告诉我如何组合这两个查询,以便在名称,电子邮件或任何标签中找到过滤器文本时匹配Person吗?

2 个答案:

答案 0 :(得分:1)

事实证明,我在这里找不到一种方法......通过https://github.com/mongoid/mongoid/issues/2845间接找到

鉴于这两个可查询:

a=Person.where({'name.first_name'=> /a/i})
b=Person.where({'name.first_name'=> /j/i})

您可以使用.selector

组合它们
Person.or(a.selector, b.selector).to_a
=> selector={"$or"=>[{"name.first_name"=>/a/i}, {"name.first_name"=>/j/i}]}

Person.and(a.selector, b.selector).to_a
=> selector={"$and"=>[{"name.first_name"=>/a/i}, {"name.first_name"=>/j/i}]}

答案 1 :(得分:0)

您根本不需要使用any_in。如果说:

:array_field => regex

然后MongoDB会自动检查array_field的每个元素对regex,你根本不关心数组。这意味着您可以将:tags签入其他条件:

regex   = /#{filter}/i
@people = Person.where(
    :$or => [
        { 'name.first_name' => regex },
        { 'name.last_name'  => regex },
        { 'email'           => regex },
        { 'tags'            => regex }
    ]
)

我还将正则表达式从查询中拉出来变成一个变量,以清楚地表明你为每次检查使用了相同的一个,然后切换到where,因为这更常见(至少根据我的经验)