mongodb - 是否可以在 Meteor 1.7+ 中订阅文本搜索光标
问题描述
以前,我曾经写过
MyCollection.find({ $text: { $search: 'foo' } }, {
fields: {
score: { $meta: "textScore" }
},
sort: {
score: { $meta: "textScore" }
}
});
但是,现在我得到一个错误
I20180926-18:26:08.708(-4)? Exception from sub mysubscription id ZeSWJcoghED3t6Eq6 Error: Exception while polling query {"collectionName":"my-collection","selector":{"$text":{"$search":"foo"}},"options":{"transform":null,"limit":25,"sort":{"score":{"$meta":"textScore"}}}}: must have $meta projection for all $meta sort keys
I20180926-18:26:08.709(-4)? at PollingObserveDriver._pollMongo (packages/mongo/polling_observe_driver.js:165:11)
I20180926-18:26:08.709(-4)? at Object.task (packages/mongo/polling_observe_driver.js:93:12)
I20180926-18:26:08.710(-4)? at Meteor._SynchronousQueue.SQp._run (packages/meteor.js:987:16)
I20180926-18:26:08.710(-4)? at packages/meteor.js:964:12
当我尝试查找更多信息时,此答案提到该fields
参数需要包含在投影中,例如
collection.find({
$text:
{
$search: filter,
$caseSensitive: false,
$diacriticSensitive: true
}
})
.project({ score: { $meta: "textScore" } })
.sort({score:{$meta:"textScore"}})
但是,Meteor没有方法.project
。
解决方案是什么?
解决方案
下面有一个创建的迷你复制指南。它显示了如何执行(索引)文本搜索作为您最初报告的引发错误的搜索。
因此,可以假设错误的来源,例如迁移到 Meteor 1.7+ / Mongo 3.6+ 或代码中。迁移很有可能包括原因,因为最近在论坛和 SO 上有很多关于升级到 1.7 问题的帖子。
因此,这里有一个简短的清单,说明可能出了什么问题:
- 新的 Mongo 版本和 node-Mongo 驱动程序版本正在用于 1.7+ - 更新是否也正确更新了这些?如果在生产中-您是否在数据库服务器上更新到相应的 Mongo 版本?
- 从 Mongo 3.2 开始,有一个新的第 3 版文本索引正在使用中。也许您以前的 Meteor 版本在执行时使用了带有以前文本索引的旧 Mongo
db.createIndex
。我没有发现任何信息表明它破坏了向后兼容性,但这可能是一个可能的原因。如果您在 dev 上,您可以通过执行轻松验证db.collection.getIndexes()
. 例如,以下创建的复制项目具有以下输出:
获取当前索引:
meteor:PRIMARY> db.texts.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "meteor.texts"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "text_text",
"ns" : "meteor.texts",
"weights" : {
"text" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]
- 如果原因是由于索引版本不匹配,您可以删除索引并重新创建它以使版本匹配。
- 如果仍然存在问题并且您无法解决,您仍然可以依赖
Mongo.Collection.rawCollection
, 允许对集合进行本机操作。请注意这个关于将本机 Mongo 操作集成到 Meteor 环境的扩展要求的答案
复制工作文本搜索,包括 $meta "textScore" 分数:
为了验证它是否正在使用新项目(Release METEOR@1.7.0.5
),您可以重现以下步骤:
- 创建一个新项目并安装 faker(快速创建一些文本):
$ meteor create metasearch
$ cd metasearch
$ meteor npm install --save faker
$ meteor
- 创建一个名为
Texts
in的集合/imports/Texts.js
:
import { Mongo } from "meteor/mongo"
export const Texts = new Mongo.Collection('texts')
- 将以下服务器代码传递到
/server/main.js
:
import { Meteor } from 'meteor/meteor'
import { Texts } from '../imports/Texts'
Meteor.startup(() => {
import { lorem } from 'faker'
for (let i = 0; i < 5; i++) {
Texts.insert({
title: lorem.words(),
text: lorem.text()
})
}
})
Meteor.publish('search', function searchpub (filter) {
const cursor = Texts.find({
$text: {
$search: filter,
$caseSensitive: false,
$diacriticSensitive: false,
}
}, {
fields: {
score: {$meta: 'textScore'},
},
sort: {
score: {$meta: 'textScore'},
},
})
// fallback if cursor is undefined
if (cursor && cursor.count && cursor.count() >= 0) {
return cursor
} else {
this.ready()
}
})
正如您所看到的,它使用默认的“查询、投影和排序在一个文档中”结构,正如您最初发布的那样。
- 通过以下方式扩展
/client/main.js
代码:
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
import {Texts} from '../imports/Texts'
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
const instance = this
instance.autorun(() => {
const cursor = instance.subscribe('search', 'dolor') // use a word, that often occurs
if (cursor.ready()) {
console.log(Texts.find().fetch())
}
})
});
// ... rest of the file
- 打开一个新的终端选项卡并打开 mongo shell 并创建一个新的文本索引:
$ meteor mongo
$ db.texts.createIndex({text:"text"})
输出应类似于:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1,
"operationTime" : Timestamp(1538031016, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1538031016, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
- 清理,取消正在运行的流星并重新启动。
与此同时,Meteor.startup
诱导插入应该已经创建了大量要搜索的文档,但它们可能还没有被添加到索引中。
您可以取消正在运行的实例并再次重新启动几次(或增加启动时要插入的文档数量)以获得大量匹配。
- 运行客户端并查看潜艇
在localhost:3000
默认情况下运行时,您应该得到类似的输出,如下所示:
Array (51) […]
0: {…}
_id: "n2WhMskCXBm7ziZea"
score: 1.0416666666666667
text: "Dolor at sed et dolorem tenetur a dolore voluptate incidunt. Rerum corrupti officia aut tenetur nisi officiis voluptas soluta. Fugiat eos sed expedita inventore. Esse cupiditate qui. Facere dolor quisquam ipsa a facere praesentium. Aut sunt mollitia dolore tenetur."
title: "quia est fuga"
<prototype>: Object { … }
1: {…}
_id: "QjAcZQLTH8Mc3jDzS"
score: 1.0110294117647058
text: "Sequi dolores omnis sequi consequatur laborum et asperiores. Accusantium repellat magnam est aut suscipit enim iure. Qui qui aut cupiditate necessitatibus commodi qui quia. Ut tempore autem provident maiores cumque necessitatibus dolores accusantium. Nostrum ut ut sunt adipisci qui consequuntur explicabo voluptas. Minima praesentium sunt facere doloribus non at dolor dolore est."
title: "est explicabo omnis"
<prototype>: Object { … }
推荐阅读
- typo3 - 使用 extbase 的 QueryBuilder 随机选择记录
- django - 将旧域重定向到新域,包括 /en/
- javascript - 将新对象推入数组 angular 7 后视图没有更新?
- android - 使用返回按钮返回上一个屏幕
- apache - 使用 Apache Camel 发出 http 请求
- php - 将表单外的值传递到url PHP中的另一个页面
- ruby-on-rails - 设计 - 在令牌无效的情况下不想打开重置密码页面
- python - 如何避免类继承
- python - 具有多个组合 STL 文件的 VTK
- c# - 更改 ASP.Net 会话 ID - 通过 AJAX 从桌面应用程序调用