Reputation: 97
I'd like to perform the equivalent of this Mongo shell command in meteor(server-side, of course):
db.articles.find(
{ $text: { $search: "apple pie" } },
{ score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } ).limit(10)
I have been able to do:
return Articles.find( { $text: { $search: "apple" } },
{ sort: {"name":1}, limit:20});
However, searching for "pie apple" doesn't work - it only does exact matching. Neither does trying to sort by score.
I am using mongo 2.6.3 with a text index on the name field in articles. Searching from within mongo shell works perfectly.
Also, has anyone successfully implemented a text search with a different approach? My database has 10k entries and I only need to search within a single field, and return 20 best matches.
Upvotes: 2
Views: 990
Reputation: 21299
3 steps (meteor 1.0.4+) now using MongoDB 3.0. Assuming you already have the YourCollection collection i.e.
YourCollection = new Meteor.Collection("yourCollection");
A. Index your collection (server side) here below is how to index all the fields, more info here
Meteor.startup(function (){
YourCollection._ensureIndex(
{"$**": "text"},
{"name": "searchIndex"}
); }
B. Create the publication (server side)
Meteor.publish("search-yourCollection", function(searchField)
{
return YourCollection.find({"$text": {"$search": searchField}},
{
fields: {
score: {$meta: "textScore"}
},
sort: {
score: {$meta: "textScore"}
}
});
});
C. Subscribe to the publication and find (client side)
var whatToSearch = "abc"; // can be taken out of the session
Meteor.subscribe("search-yourCollection", whatToSearch);
var results = YourCollection.find({score:{"$exists":true}});
Remark: The publication will add a score property to all the returned items. Ensuring this property exists within the find function {"$exists":true} will make sure you are finding the elements returned by the search-yourCollection publication. This is mandatory if you are subscribing to another publication adding items into YourCollection published set.
Upvotes: 3
Reputation: 97
I've been able to get this to work using something similar to: Implementing MongoDB 2.4's full text search in a Meteor app
The differences are:
MongoInternals.defaultRemoteCollectionDriver().mongo.db.executeDbCommand
and the searchDinosaurs function in the link above looks like:
if (query && query !== '') {
var searchResults = _searchArticles(query);
var results = [];
for (var i = 0; i < searchResults.length; i++) {
results.push({
id: searchResults[i].obj._id,
score: searchResults[i].score});
}
var ids = [];
results.sort(function(a,b) { return a.score < b.score } );
for (var i = 0; i < 20; i++) {
if (results[i]!=null){
ids.push(results[i].id);
}
}
return ids;
Here I'm sorting the results on score and returning the top 20 id's. The only issue is, once the user is subscribed to these 20 articles, I have to find and sort them once again client-side using regex search in minimongo. If anyone has suggestions or improvements, I'd love to hear them.
Upvotes: 1