言語サポート付きのMongoDbテキスト検索

Nov 22 2020

MongoDBの言語テキスト検索に問題があります。一部のレコードでは検索がうまく機能し、一部のレコードではまったく機能しません。

検索したい材料のリストがあります。材料はいくつかの言語であり、私は単数形と複数形の世話をするのが好きです。

これが私の例です

スキーマ

{
  translation: [
    {
      language: {
        type: String,
        required: true
      },
      name: {
        type: String,
        required: true
      }
    }
  ],
  calories: {
    "type": Number
  },
  protein: {
    "type": Number
  },
  carbohydrate: {
    "type": Number
  },
  fat: {
    "type": Number
  }
}

インデックス

foodSchema.index( { "translation.name": "text" }, { default_language: "german" } )

DBからインデックスを読み取る

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

記録

{
  calories: 1,
  protein: 2,
  carbohydrate: 3,
  fat: 4,
  translation: [
    {
      _id: ObjectId('5fba87d13ad6404108191670'),
      language: 'german',
      name: 'gurke'
    },
    {
      _id: ObjectId('5fba87d13ad6404108191671'),
      language: 'english',
      name: 'cucumber'
    },
    {
      _id: ObjectId('5fba87d13ad6404108191672'),
      language: 'spanish',
      name: 'pepino'
    }
  ]
}

// ----

{    
  calories: 4,
  protein: 3,
  carbohydrate: 2,
  fat: 1,
  translation: [
    {
      _id: ObjectId('5fba87d13ad6404108191674'),
      language: 'german',
      name: 'huhn'
    },
    {
      _id: ObjectId('5fba87d13ad6404108191675'),
      language: 'english',
      name: 'chicken'
    },
    {
      _id: ObjectId('5fba87d13ad6404108191676'),
      language: 'spanish',
      name: 'pollo'
    }
  ]
}

データの検索

db.getCollection('foods').find({$text: { $search: "gurke" }}) //works
db.getCollection('foods').find({$text: { $search: "gurken" }}) //works
db.getCollection('foods').find({$text: { $search: "cucumber" }}) //works
db.getCollection('foods').find({$text: { $search: "cucumbers" }}) //works
db.getCollection('foods').find({$text: { $search: "huhn" }}) //works
db.getCollection('foods').find({$text: { $search: "hühner" }}) //works
db.getCollection('foods').find({$text: { $search: "chicken" }}) // no result
db.getCollection('foods').find({$text: { $search: "chickens" }}) //no result
db.getCollection('foods').find({$text: { $search: "pepino" }}) //no result

MongoDbのドキュメントによると: https://docs.mongodb.com/manual/tutorial/specify-language-for-text-index/

インデックス付きデータに関連付けられているデフォルトの言語によって、単語の語根を解析(つまりステミング)し、ストップワードを無視するルールが決まります。

  • デフォルトの言語のみがサポートされているという意味ですか?
  • なぜそれはキュウリには効くのに鶏肉には効かないのですか?

鶏肉のストップワードもチェックしていました。 https://github.com/mongodb/mongo/blob/master/src/mongo/db/fts/stop_words_english.txt

ご協力ありがとうございました!

回答

1 Minsky Nov 22 2020 at 17:06

問題はインデックスではなく、正しいですが、追加する必要がある$languageか、デフォルトの言語を使用します(少なくともを使用する場合$text)。試してみてください

 db.collection.find({$text:{$search:"pollo", $language:"spanish"}})

$language ドキュメント

指定しない場合、検索ではインデックスのデフォルト言語が使用されます。

また、あなたが実行する場合

 db.collection.find({$text:{$search:"pollo"}}).explain()

クエリがデフォルトの言語を使用していることがわかります。