MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB :comment effectuer une recherche de texte et trier par date

Indépendamment des autres clés d'index composé, vous devez inclure le $meta pour le "textScore" afin d'obtenir le bon tri :

db.collection.find(
    { "$text": { "$search": "\"[email protected]\""}},
    { "score": { "$meta": "textScore" } }
).sort({
    "score": { "$meta": "textScore" }, "Date": 1
})

Donc, naturellement, vous voulez que ce "score" soit trié en premier, puis par "Date" afin que les éléments soient correctement classés en fonction de la pertinence de la recherche.

L'ordre de l'index n'a pas d'importance, mais bien sûr vous ne pouvez avoir qu'"un" index de texte. Assurez-vous donc de supprimer tous les autres avant de créer :

db.collection.createIndex({ 
   "From": "text",
   "To": "text",
   "CC":"text", 
   "BCC": "text", 
   "Date":1
})

Recherchez les index qui sont à jour avec :

db.collection.getIndicies()

Ou laissez tout tomber et recommencez à zéro :

db.collection.dropIndexes()

Pour les données que vous semblez rechercher, j'aurais pensé qu'un index composé régulier sur chaque champ devrait mieux vous convenir. La recherche d'adresses "e-mail" doit être une "correspondance exacte", et si vous attendez plusieurs éléments pour chaque champ, ils doivent être des tableaux de chaînes, comme ceci :

{
    "TO": ["[email protected]"],
    "FROM": ["[email protected]"],
    "CC": ["[email protected]","[email protected]"],
    "BCC": [],
    "Date": ISODate("2015-07-27T13:42:05.535Z")
}

Ensuite, vous avez besoin d'index séparés sur chaque champ, éventuellement en composé avec "Date" comme ceci :

db.email.createIndex({ "TO": 1, "Date": 1 })
db.email.createIndex({ "FROM": 1, "Date": 1 })
db.email.createIndex({ "CC": 1, "Date": 1 })
db.email.createIndex({ "BCC": 1, "Date": 1 })

Et requête avec un $or condition :

db.email.find({
    "$or": [
        { "TO": "[email protected]" },
        { "FROM": "[email protected]" },
        { "CC": "[email protected]" },
        { "BCC": "[email protected]" }
    ],
    "Date": { "$lt": new Date() }
})

Si vous regardez le .explain(true) (verbeux) de cela, vous devriez voir que le plan gagnant est une "intersection d'index" de tous les index spécifiés. Cela s'avère très efficace car chaque champ (et index sélectionné) a une valeur de correspondance exacte et une correspondance de plage à la date indexée.

Ce sera beaucoup mieux pour vous que la "correspondance floue" des recherches de texte. Même les expressions régulières devraient mieux fonctionner ici en général (pour les adresses e-mail) et surtout si elles sont "ancrées" ^ au début de la chaîne.

Les index de texte sont destinés à correspondre à des "mots semblables à des jetons", mais cela ne devrait pas être vos données. Le $or n'a pas l'air bien, mais il devrait faire un bien meilleur travail.