sql >> Database >  >> NoSQL >> MongoDB

MongoDB:tekst zoeken en sorteren op datum

Ongeacht andere samengestelde indexsleutels, moet u de opnemen $meta voor de "textScore" om de juiste sortering te krijgen:

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

U wilt natuurlijk dat die "score" eerst wordt gesorteerd en vervolgens op "Datum", zodat de zaken correct worden gerangschikt op relevantie van de zoekopdracht.

De volgorde van de index doet er niet toe, maar u kunt natuurlijk maar "één" tekstindex hebben. Zorg er dus voor dat je alle anderen laat vallen voordat je het volgende maakt:

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

Zoek naar indexen die actueel zijn met:

db.collection.getIndicies()

Of laat alles vallen en begin opnieuw:

db.collection.dropIndexes()

Voor de gegevens waarop u lijkt te zoeken, had ik gedacht dat een regelmatige samengestelde index op elk veld beter bij u zou passen. Zoeken naar "e-mailadressen" moet een "exacte overeenkomst" zijn, en als u meerdere items voor elk veld verwacht, moeten dit arrays van tekenreeksen zijn, zoals:

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

Dan heb je aparte indexen nodig op elk veld, eventueel in samenstelling met "Datum" zoals:

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

En zoek een zoekopdracht met een $or staat:

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

Als je kijkt naar de .explain(true) (uitgebreide) uitvoer daarvan, je zou moeten zien dat het winnende plan een "indexkruispunt" is van alle gespecificeerde indexen. Dit blijkt zeer efficiënt te zijn, aangezien elk veld (en geselecteerde index) een exacte overeenkomstwaarde heeft en een bereikovereenkomst op de geïndexeerde datum.

Dat zal een stuk beter voor je zijn dan de "fuzzy matching" van tekstzoekopdrachten. Zelfs reguliere expressies zouden hier in het algemeen beter moeten werken ( voor e-mailadressen ) en vooral als ze "verankerd" zijn ^ naar het begin van de tekenreeks.

Tekstindexen zijn bedoeld om "woord-achtige tokens" te matchen, maar dit zouden niet uw gegevens moeten zijn. De $or ziet er niet mooi uit, maar het zou veel beter moeten werken.




  1. Modellering van blogs en beoordelingen in mongodb en nodejs

  2. Mongodb find() query :retourneert alleen unieke waarden (geen duplicaten)

  3. Hoe MongoDB te schalen?

  4. MongoDB {aggregatie $ match} versus {find} snelheid