MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

MongoDB:Como fazer uma pesquisa de texto e classificar por uma data


Independentemente de outras chaves de índice composto, você precisa incluir o $meta para o "textScore" para obter a classificação correta:
db.collection.find(
    { "$text": { "$search": "\"[email protected]\""}},
    { "score": { "$meta": "textScore" } }
).sort({
    "score": { "$meta": "textScore" }, "Date": 1
})

Então, naturalmente, você quer que a "pontuação" seja classificada primeiro e depois por "Data" para que as coisas sejam classificadas corretamente pela relevância da pesquisa.

A ordem do índice não importa, mas é claro que você só pode ter "um" índice de texto. Portanto, certifique-se de descartar todos os outros antes de criar:
db.collection.createIndex({ 
   "From": "text",
   "To": "text",
   "CC":"text", 
   "BCC": "text", 
   "Date":1
})

Procure por índices que estão atualizados com:
db.collection.getIndicies()

Ou simplesmente largue tudo e comece de novo:
db.collection.dropIndexes()

No entanto, para os dados que você parece estar pesquisando, eu teria pensado que um índice composto regular em cada campo seria melhor para você. A procura de endereços de "e-mail" deve ser uma "correspondência exata" e, se você espera vários itens para cada campo, eles devem ser matrizes de strings, assim:
{
    "TO": ["[email protected]"],
    "FROM": ["[email protected]"],
    "CC": ["[email protected]","[email protected]"],
    "BCC": [],
    "Date": ISODate("2015-07-27T13:42:05.535Z")
}

Então você precisa de índices separados em cada campo, possivelmente em composto com "Data" assim:
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 consulte com um $or doença:
db.email.find({
    "$or": [
        { "TO": "[email protected]" },
        { "FROM": "[email protected]" },
        { "CC": "[email protected]" },
        { "BCC": "[email protected]" }
    ],
    "Date": { "$lt": new Date() }
})

Se você olhar para o .explain(true) (verbose) a partir disso, você deve ver que o plano vencedor é uma "interseção de índice" de todos os índices especificados. Isso funciona para ser muito eficiente, pois cada campo (e índice selecionado) tem um valor de correspondência exata e uma correspondência de intervalo na data indexada.

Isso será muito melhor para você do que a "correspondência difusa" das pesquisas de texto. Mesmo as expressões regulares devem funcionar melhor aqui em geral ( para endereços de e-mail ) e especialmente se estiverem "ancoradas" ^ para o início da string.

Índices de texto destinam-se à correspondência de "tokens semelhantes a palavras", mas esses não devem ser seus dados. O $or não parece bom, mas deve fazer um trabalho muito melhor.