2015-12-12 18 views
5

Ho un problema nell'utilizzo dell'API Java per MongoDB. Ho creato una query utilizzando Robomongo:API Java MongoDB: ricerca full-text

db.collection.find(
    {$text : {$search : "\"expression\" keyword"}}, 
    {score : {$meta : "textScore"}} 
).sort({score : {$meta : "textScore"}}) 

Ora vorrei creare la stessa query utilizzando API Java:

DBObject searchCommand = new BasicDBObject(
    "$text", new BasicDBObject("$search", "\"expression\" keyword") 
).append(
    "score", new BasicDBObject("'$meta'", "textScore") 
); 

DBObject sorting = new BasicDBObject(
    "score", new BasicDBObject("'$meta'", "textScore") 
); 

DBCursor result = collection.find(searchCommand).sort(sorting); 

Il problema è che questo codice non funziona. La query:

DBObject searchCommand = new BasicDBObject(
    "$text", new BasicDBObject("$search", "\"expression\" keyword") 
); 

funziona perfettamente. Dopo aver aggiunto la seconda parte, tutti i risultati diventano invisibili. Cosa c'è di più, questa linea:

DBCursor result = collection.find(searchCommand).sort(sorting); 

genera MongoException (BadValue cattiva specifica di ordinamento). Quando rimuovo il richiamo del metodo sort() l'Eccezione non è presente, ma ancora non ho alcun risultato (se appendo "punteggio").

Ho trovato una soluzione a questo problema, ma utilizzando Spring. Non vorrei usare altre librerie. Inoltre, sono un principiante in MongoDB. Grazie per il tuo aiuto e il tuo tempo, evviva.


AGGIORNAMENTO. Problema risolto. Aggiungendo "punteggio" per interrogare searchCommand passato come primo parametro di find() è sbagliato. "Score" dovrebbe essere passato in DBOBJECT separata come secondo parametro del metodo find() come segue:

DBObject search = new BasicDBObject(
    "$text", new BasicDBObject("$search", "\"expression\" keyword") 
); 

DBObject project = new BasicDBObject(
    "score", new BasicDBObject("$meta", "textScore") 
); 

DBObject sorting = new BasicDBObject(
    "score", new BasicDBObject("$meta", "textScore") 
); 

DBCursor result = collection.find(search, project).sort(sorting); 

risposta

6

avete ottenuto molto vicino, con quello che hai provato.

Si noti che in,

db.collection.find(
    {$text : {$search : "\"expression\" keyword"}}, 
    {score : {$meta : "textScore"}} 
).sort({score : {$meta : "textScore"}}) 
  • {$text : {$search : "\"expression\" keyword"}} - è la parte query.

  • {score : {$meta : "textScore"}} - è la parte projection.

a quello che hai cercato di attuare utilizzando il driver Java,

DBObject searchCommand = new BasicDBObject(
    "$text", new BasicDBObject("$search", "\"expression\" keyword") 
).append(
    "score", new BasicDBObject("'$meta'", "textScore") 
); 

finirebbe per produrre,

{$text:{$search:"\"expression\" keyword"},"score":{"meta":"textscore"}} 

che non è equivalente alla query nativo. Anche la dichiarazione destinata aprojection fa parte dello stesso query.

Si noti che, questo finisce alla ricerca di un campo denominato score, dal momento che è ormai diventata una parte della query e non il projection.

È possibile modificare facilmente i vostri DBObject casi, per renderlo una parte del parametro projection e che avrebbe funzionato:

DBObject findCommand = new BasicDBObject(
    "$text", new BasicDBObject("$search", "keyword") 
); 

DBObject projectCommand = new BasicDBObject(
    "score", new BasicDBObject("$meta", "textScore")); 

DBObject sortCommand = new BasicDBObject(
    "score", new BasicDBObject("$meta", "textScore") 
); 
DBCursor result = collection.find(
            findCommand ,projectCommand) 
            .sort(sortCommand); 
+1

ringrazio molto :) Sembra che ho scoperto il mio problema qualche istante prima del tuo risposta. Comunque, grazie per la spiegazione completa. – bargro