MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB:come eseguire una ricerca di testo e ordinare per data

Indipendentemente dalle altre chiavi di indice composte, è necessario includere $meta per il "textScore" per ottenere l'ordinamento corretto:

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

Quindi, naturalmente, vuoi che il "punteggio" venga ordinato prima e poi per "Data" in modo che le cose siano classificate correttamente in base alla pertinenza della ricerca.

L'ordine dell'indice non ha importanza, ma ovviamente puoi avere solo "uno" indice di testo. Quindi assicurati di eliminare tutti gli altri prima di creare:

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

Cerca gli indici aggiornati con:

db.collection.getIndicies()

Oppure lascia tutto e ricomincia da capo:

db.collection.dropIndexes()

Tuttavia, per i dati su cui sembra che stai cercando, avrei pensato che un indice composto regolare su ciascun campo dovesse adattarsi meglio a te. La ricerca di indirizzi "email" dovrebbe essere una "corrispondenza esatta" e se prevedi più elementi per ogni campo, dovrebbero essere array di stringhe, in questo modo:

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

Quindi hai bisogno di indici separati su ciascun campo, possibilmente in formato composto con "Data" in questo modo:

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 })

E interroga con un $or condizione:

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

Se guardi il .explain(true) (verboso) da ciò, dovresti vedere che il piano vincente è una "intersezione di indici" di tutti gli indici specificati. Questo risulta essere molto efficiente poiché ogni campo (e indice selezionato) ha un valore di corrispondenza esatto e una corrispondenza di intervallo nella data indicizzata.

Sarà molto meglio per te rispetto alla "corrispondenza sfocata" delle ricerche di testo. Anche le espressioni regolari dovrebbero funzionare meglio qui in generale ( per gli indirizzi e-mail ) e soprattutto se sono "ancorate" ^ all'inizio della stringa.

Gli indici di testo sono pensati per la corrispondenza di "token simili a parole", ma questi non dovrebbero essere i tuoi dati. Il $or non ha un bell'aspetto, ma dovrebbe fare un lavoro molto migliore.