PHP MongoDB全文搜索和排序

4

我需要使用全文索引进行搜索,以下代码可行:

$cursor=$collection->find(array('$text'=>(array('$search'=>$s))),
                    array("score"=> array('$meta'=>"textScore"))
        );

我尝试使用以下方式对光标进行排序:
$cursor =$cursor->sort(array("score"=>1));

当我尝试阅读时

var_dump($cursor->getNext());

我得到了这个错误 未捕获的异常'MongoCursorException',消息为'localhost:27017:无法规范化查询:BadValue不能在$meta投影上有非-$meta排序'

有什么想法?


尝试从find()中消除“score”搜索条件。很可能它不允许在同一键值上查找和排序。 - dkakoti
但是,如果我在搜索中构建的字段上要求排序,该怎么办?如果我从db.collection.find()的第二个字段中删除它,那么如何保存作为元数据构建的分数?我尝试过删除,但排序不起作用,我应该如何编写它?谢谢。 - user3535936
你的数组('$search'=>$s)周围有额外的括号()。请参考下面的答案,使用sort()函数解决问题。 - bjori
1个回答

5

您正在尝试按元字段而非普通字段名进行排序。

$collection->find() 的第二个参数决定了查询时返回的文档中哪些字段需要或不需要被返回。

这类似于 SQL 数据库中的 SELECT *... vs SELECT field1, field2 ...

现在,在 MongoDB 2.6 中有一个额外的关键字 $meta 可以在此处使用。使用该关键字可以“注入”字段名到返回的文档中(否则实际上不存在该字段)。该注入字段名的值将来自正在执行的文档或查询的某种“元数据”。

$text查询操作符是一个例子,它拥有有关匹配文档的更多信息。不幸的是,它无法告诉您有关此额外信息的内容,因为这样做会以意想不到的方式操作您的文档。但是,它会将元数据附加到文档上,您可以自行决定是否需要它。

$text操作符创建的元数据使用关键字"textScore"。如果您想包含该数据,可以通过将其分配给您选择的字段名称来实现:

array("myFieldname" => array('$meta' => 'keyword'))

例如,在$text搜索(textScore)的情况下,我们可以通过将此数组作为第二个参数传递给$collection->find()来将字段名“score”注入到我们的文档中:
array("score" => array('$meta' => 'textScore'))

现在我们已经将一个名为“score”的字段注入到我们的返回文档中,该字段具有来自$text搜索的“textScore”值。
但是由于这仍然只是文档的元数据,如果您想在执行查询之前继续使用此值进行任何后续操作,则仍必须将其称为$meta数据。
这意味着,要对该字段进行排序,您必须对$meta projection进行排序。
array('score' => array('$meta' => 'textScore'))

您的完整示例如下:

<?php
$mc = new MongoClient();


$collection = $mc->selectCollection("myDatabase", "myCollection");

$string = "search string";
$cursor = $collection->find(
    array('$text' => array('$search' => $string)),
    array('score' => array('$meta' => 'textScore'))
);

$cursor = $cursor->sort(
    array('score' => array('$meta' => 'textScore'))
);

foreach($cursor as $document) {
    var_dump($document);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接