使用solr进行缺失值的负面构造查询的麻烦

时间:2014-08-29 15:55:10

标签: solr solr4 faceted-search

我正在为我们的网站制作产品过滤器,并且在使用“facet.missing = true”方面遇到了一些困难。

我知道我应该使用像“fq = -facetField:[* TO *]”之类的查询过滤器来将结果过滤到缺少该字段的产品。

我为我的应用程序构建了一个全局过滤器帮助器,它为所有查询动态构建fq参数,以防止任何错过基于用户权限的过滤器,基本上看起来像这样(php):

$params['fq'] = sprintf('((%s) AND (%s))', $custom, $system);

其中$ system是基于全局权限的过滤器,可能看起来像(不是实际但类似):

(isdiscontinued:0 AND ishidden:0 AND contract:3)

$ custom包含用户​​通过UI构建的实际过滤器查询。假设笔记本蓝牙过滤器的名称为fq_bluetooth,其值为:No,Yes,或者缺少值。这将使最终的fq看起来像:

((-fq_bluetooth:[* TO *]) AND ((isdiscontinued:0 AND ishidden:0 AND contract:3)))

然而,这会返回我正在为此类别发送的查询的0个产品。

如果我将过滤器查询修改为:

((fq_bluetooth:[* TO *]) AND ((isdiscontinued:0 AND ishidden:0 AND contract:3)))

然后我得到结果可以预期是+否的计数,无视未指明。

我应该如何格式化过滤器查询以使其正常工作?

[编辑]

我可能还希望将这些方面结合起来,并且可能只过滤没有蓝牙的产品或没有指定蓝牙的产品。所以也许这样(当然这也不起作用):

((-fq_bluetooth:[* TO *] OR fq_bluetooth:"No") AND ((isdiscontinued:0 AND ishidden:0 AND contract:3)))

我注意到debugQuery,我看到了一个过滤器查询,如:

fq_bluetooth:("No" OR -[* TO *])

被解析为:

fq_bluetooth:No -fq_bluetooth:[* TO *]

我没有在解析的查询中看到OR - 而且根据我的研究,fq参数查询不支持OR运算符(??)。

也许OR正在工作,但由于否定查询似乎本身就失败了,也许这就是为什么我不能看到OR工作的原因就像这样。

1 个答案:

答案 0 :(得分:4)

删除不必要的括号并将过滤器查询拆分为两个过滤查询,一个用于系统限制,另一个用于用户生成的过滤。

1)由于您希望满足请求中的两个逻辑要求(安全限制和用户生成的过滤),为什么不用两个过滤查询重写您的查询?

一个用于系统权限,另一个用于从应用UI生成的查询(转义省略):

... fq = isdiscontinued:0 AND ishidden:0 AND contract:3& fq = -fq_bluetooth:[* TO *]

这对filter query caching

有帮助

2)至于你的具体查询问题,通过试验,似乎括号的存在正在改变预期的结果。使用本地实例进行测试,我有以下内容,如果我使用您的语法,((-ProcedeImageElectronique:[* TO *]) AND (Pays:France AND GrandeCategorie:FILM))返回0结果:

{
  "responseHeader": {
    "status": 0,
    "QTime": 1,
    "params": {
      "facet": "off",
      "indent": "true",
      "q": "*:*",
      "wt": "json",
      "fq": "((-ProcedeImageElectronique:[* TO *]) AND (Pays:France AND GrandeCategorie:FILM))"
    }
  },
  "response": {
    "numFound": 0,
    "start": 0,
    "maxScore": 0,
    "docs": []
  }
}

-ProcedeImageElectronique:[* TO *] AND Pays:France AND GrandeCategorie:FILM对比,导致预期的行为:

{
  "responseHeader": {
    "status": 0,
    "QTime": 1,
    "params": {
      "facet": "off",
      "indent": "true",
      "q": "*:*",
      "wt": "json",
      "fq": "-ProcedeImageElectronique:[* TO *] AND Pays:France AND GrandeCategorie:FILM"
    }
  },
  "response": {
    "numFound": 1733,
    "start": 0,
    "maxScore": 1,
    "docs": [...]
  }
}

同样,使用两个过滤器查询会返回预期结果:

{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "facet": "off",
      "indent": "true",
      "q": "*:*",
      "wt": "json",
      "fq": [
        "-ProcedeImageElectronique:[* TO *]",
        "GrandeCategorie:FILM AND Pays:France"
      ]
    }
  },
  "response": {
    "numFound": 1733,
    "start": 0,
    "maxScore": 1,
    "docs": [...]
  }
}

编辑:this post清楚地解释了为什么使用括号可能导致意外结果。引用:

  

如果顶级BoolenQuery包含嵌套内部的某个地方   BooleanQuery,它只包含否定子句,即嵌套查询   将不会被修改,并且(根据定义)不匹配任何文件    - 如果需要,则表示外部查询不匹配。