MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB:So führen Sie eine Textsuche durch und sortieren nach Datum

Unabhängig von anderen zusammengesetzten Indexschlüsseln müssen Sie einschließen $meta für den "textScore", um die richtige Sortierung zu erhalten:

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

Natürlich möchten Sie, dass diese "Punktzahl" zuerst sortiert wird und dann nach "Datum", damit die Dinge korrekt nach Relevanz der Suche geordnet werden.

Die Reihenfolge der Indexe spielt keine Rolle, aber Sie können natürlich nur "einen" Textindex haben. Stellen Sie also sicher, dass Sie alle anderen löschen, bevor Sie Folgendes erstellen:

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

Suchen Sie nach Indizes, die aktuell sind mit:

db.collection.getIndicies()

Oder lassen Sie einfach alles stehen und fangen Sie neu an:

db.collection.dropIndexes()

Für die Daten, nach denen Sie anscheinend suchen, hätte ich gedacht, dass ein regulärer zusammengesetzter Index für jedes Feld besser zu Ihnen passt. Die Suche nach "E-Mail"-Adressen sollte eine "genaue Übereinstimmung" sein, und wenn Sie mehrere Elemente für jedes Feld erwarten, sollten sie Arrays von Zeichenfolgen sein, etwa so:

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

Dann benötigen Sie separate Indizes für jedes Feld, möglicherweise in Verbindung mit "Datum" wie folgt:

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

Und fragen Sie mit einem $or ab Bedingung:

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

Wenn Sie sich den .explain(true) (ausführliche) Ausgabe davon, sollten Sie sehen, dass der Gewinnerplan eine "Index-Schnittmenge" aller angegebenen Indizes ist. Dies erweist sich als sehr effizient, da jedes Feld ( und jeder ausgewählte Index ) einen exakten Übereinstimmungswert und eine Bereichsübereinstimmung am indexierten Datum hat.

Das wird viel besser für Sie sein als das "Fuzzy-Matching" von Textsuchen. Auch reguläre Ausdrücke sollten hier generell besser funktionieren ( für E-Mail-Adressen ) und besonders wenn sie "verankert" ^ sind bis zum Anfang der Zeichenfolge.

Textindizes sind für "wortähnliche Token" gedacht, aber dies sollten nicht Ihre Daten sein. Der $oder sieht nicht schön aus, sollte aber viel besser funktionieren.