Recherche de texte MongoDb avec prise en charge de la langue

Nov 22 2020

J'ai des problèmes avec la recherche de texte de langue de MongoDB. Pour certains enregistrements, la recherche fonctionne très bien et pour certains enregistrements, elle ne fonctionne pas du tout.

J'ai une liste d'ingrédients que j'aimerais rechercher. Les ingrédients sont en plusieurs langues et j'aime m'occuper du singulier et du pluriel.

Voici mon exemple

Schéma

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

Indice

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

Lire l'index à partir de la base de données

[
    {
        "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
    }
]

Registres

{
  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'
    }
  ]
}

Recherche de données

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

La documentation de MongoDb dit: https://docs.mongodb.com/manual/tutorial/specify-language-for-text-index/

La langue par défaut associée aux données indexées détermine les règles pour analyser les racines des mots (c'est-à-dire les racines) et ignorer les mots vides.

  • Cela signifie-t-il que seule la langue par défaut est prise en charge?
  • Pourquoi ça marche pour le concombre mais pas pour le poulet?

Je vérifiais également les mots vides pour n'importe quel poulet. https://github.com/mongodb/mongo/blob/master/src/mongo/db/fts/stop_words_english.txt

Merci de votre aide!

Réponses

1 Minsky Nov 22 2020 at 17:06

Le problème n'est pas l'index, c'est correct, mais vous devez ajouter $languageou il utilise la langue par défaut (au moins lors de l'utilisation $text). Essayer

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

$language Docs

S'il n'est pas spécifié, la recherche utilise la langue par défaut de l'index.

Aussi, si vous exécutez

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

Vous découvrirez que la requête utilise la langue par défaut.