【问题标题】:Mongoose not creating text indexes for multiple fieldsMongoose 不为多个字段创建文本索引
【发布时间】:2019-12-18 03:27:15
【问题描述】:

我有一个基本的 mongoose 架构,需要我在它的两个字段上创建一个文本索引:名称和描述。

这是我的猫鼬连接选项:

mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useNewUrlParser', true);

const mongoOptions = {
  useNewUrlParser: true,
  autoIndex: false,
  reconnectTries: Number.MAX_VALUE,
  reconnectInterval: 500,
  poolSize: 10,
  bufferMaxEntries: 0
};

mongoose.connect(MONGOURI, mongoOptions);

这是我的架构:

const ASchema = new mongoose.Schema({
  name: {type: String, text: true, index: true, required: true, maxlength: [100, 'Name must be less than 100 characters']},
  description: {type: String, text: true, index: true, required: true, maxlength: [500, 'Description must be less than 500 characters']},
  meta: {tags: [String]}
});

ASchema.options.autoIndex = true;

ASchema.index({
  name: 'text',
  description: 'text',
}, {
  weights: {
    name: 5,
    description: 3,
  },
});

var A = mongoose.model("AModel", ASchema);

module.exports = A;

由于查询的某些原因,我使用以下方法创建:

app.post('/search', (req, res, next) => {
  let query = req.query.q
  console.log(query);
  A.find({
    $text: { $search: query }
  }, { score: { $meta: "textScore" } }
  ).sort( { score: { $meta: "textScore" } } )
  .then(q => {
    console.log(q); res.send(q)
  })
  .catch(next)
});

只有当我的查询字符串在 name 字段中时,我才会得到结果。 然而,当我输入描述中出现的句子或单词 ONLY 时,我会返回一个空数组。

在我的 mongo shell 上调用 db.amodels.getIndexes() 会返回以下内容:

[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "adatabase.amodels"
        },
        {
                "v" : 2,
                "key" : {
                        "_fts" : "text",
                        "_ftsx" : 1
                },
                "name" : "name_text",
                "ns" : "adatabase.amodels",
                "background" : true,
                "weights" : {
                        "name" : 1
                },
                "default_language" : "english",
                "language_override" : "language",
                "textIndexVersion" : 3
        }
]

我可以从这个以及我的 mlab 实例中看到,我的 复合索引 尚未创建,也没有分配适当的权重。

致电db.amodels.ensureIndex({"description": "text"})

返回一个IndexOptionsConflict

{
        "operationTime" : Timestamp(1565476058, 1),
        "ok" : 0,
        "errmsg" : "Index: { v: 2, key: { _fts: \"text\", _ftsx: 1 }, name: \"description_text\", ns: \"adatabase.amodels\", weights: { description: 1 }, default_language: \"english\", language_override: \"language\", textIndexVersion: 3 } already exists with different options: { v: 2, key: { _fts: \"text\", _ftsx: 1 }, name: \"name_text\", ns: \"adatabase.amodels\", background: true, weights: { name: 1 }, default_language: \"english\", language_override: \"language\", textIndexVersion: 3 }",
        "code" : 85,
        "codeName" : "IndexOptionsConflict",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1565476058, 1),
                "signature" : {
                        "hash" : BinData(0,"FMoSr4UQZWqocfrRTFvGoa62TsY="),
                        "keyId" : NumberLong("6723301754588364801")
                }
        }
}

我只是在某个地方搞砸了吗?我当然希望如此。

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    在 mongoDB 中,您不能创建两个文本索引,即;集合的两个不同字段上的两个单字段文本索引。如果真的需要创建,您所能做的就是删除现有的(如果可以的话)并创建一个包含所有必要文本字段的新复合索引!下面是 shell 操作,或者你已经在模式中有复合索引,你可以运行你的代码。

    做这样的事情:

    db.amodels.createIndex(
       {
         name: "text",
         description: "text"
       }
     )
    

    带权重(可选):

    db.amodels.createIndex(
        {
            name: "text",
            description: "text"
        },
        {
            weights: {
                name: 5,
                description: 3
            },
            name: "name_description"
        }
    )
    

    注意: Regd.您创建索引 - 您可以开始使用 createIndex,因为 ensureIndex 已弃用 ensureIndex to createIndex

    请检查此以供参考:

    MongoDB Text Indexes

    【讨论】:

    • 谢谢!现在效果很好。有没有办法直接在我的代码中创建这个复合索引,而不必每次都使用 shell?编辑:我也刚刚注意到我在 Schema 文件中的权重没有被实现?
    • @Bdyce :您正在架构中正确创建复合索引,唯一的问题是 mongoDB 已经有一个文本索引,您不能像那样更改现有索引,您需要删除它。我不太确定 mongoose dropIndex 然后使用代码创建它!权重有什么问题?
    • 删除数据库中的所有集合后。我重新连接,这将运行我的猫鼬代码,其中应在实例上创建复合索引。相反,仅创建“名称”字段上的单个文本索引。 { "v": 2, "key": { "_fts": "text", "_ftsx": 1 }, "name": "name_text", "ns": "adatabase.amodels", "background": true, "weights": { "name": 1 }, "default_language": "english", "language_override": "language", "textIndexVersion": 3 } 如您所见,我在 Schema 文件中包含的权重尚未放入索引中。
    • 删除这个单一的“名称”索引后,我必须在 shell 中运行 db.amodels.createIndex( { name: "text", description: "text" } ) 以创建复合索引。该索引的权重也只是 {"name": 1, "description": 1} 这不是我的 Schema 文件中的权重?
    • 感谢所有帮助,问题似乎不是autoIndex: true,而是我字段上的index: truetext: true 选项。干杯。问题解决了!
    猜你喜欢
    • 2023-03-26
    • 2012-09-16
    • 2015-03-17
    • 2018-03-25
    • 2017-09-04
    • 2012-09-09
    • 2018-07-03
    • 2015-01-09
    相关资源
    最近更新 更多