nicholaides
nicholaides

Reputation: 19489

Mongo full text search with score via Ruby driver

In the Mongo documentation, it says you can do this:

db.articles.find(
   { $text: { $search: "cake" } },
   { score: { $meta: "textScore" } }
)

That works fine when I run it from the mongo console but I can't figure out how to do that via the Ruby driver.

When I do this:

articles.find('$text': { '$search': 'cake' }, score: { '$meta': 'textScore' })

I get

Mongo::Error::OperationFailure: unknown operator: $meta (2)

When I do

articles.find({ '$text': { '$search': 'cake' } }, score: { '$meta': 'textScore' })

I get results but it doesn't include the score and the log message doesn't show that it's using the score: { $meta': 'textScore' }:

{"find"=>"articles", "filter"=>{"$text"=>{"$search"=>"cake"}}}

I guess I just don't grok how the Ruby driver and Mongo CLI convert those into Mongo queries.

I'm using MongoDB version v3.2.7 and the mongo gem version 2.2.5.

Upvotes: 2

Views: 269

Answers (2)

nicholaides
nicholaides

Reputation: 19489

@farhatmihalko's answer is spot-on. To add to it, this also works:

posts
  .find("$text": { "$search": "house" })
  .projection(score: { "$meta": "textScore" }, rooms: 1)

Upvotes: 0

Farkhat Mikhalko
Farkhat Mikhalko

Reputation: 3645

Let's look to structure of mongo command:

db.collection.find(
   <query>,
   { score: { $meta: "textScore" } }
)

We see that command contains two parts (in this case find)

  1. <query>
  2. options hash

Structure of command in mongo-driver very similar to mongo. But some things are not simple.

In mongo-driver we have Mongo::Collection::View, check (link to source):

articles.find({ '$text': { '$search': 'cake' } }.class # => Mongo::Collection::View

So after analyzing code, i found that you can use projection option, but it is tricky:

articles.find(
 { "$text" => { "$search" => "cake" } }, 
 projection: { 
   "score" => { "$meta" => "textScore" }, 
   some_field: 1
 })

My test was:

posts.find(
  { "$text" => { "$search" => "house" } }, 
  projection: { "score" => { "$meta" => "textScore" }, rooms: 1 }
)

Results is:

{"_id"=>BSON::ObjectId('53f5c8b54465764a82fb0000'), 
 "rooms"=>2.0, 
 "score"=>0.5004448398576512}

Upvotes: 2

Related Questions