Full-text search with Meteor.js and MongoDB - mongodb

I am experimenting with Meteor.js and looking for a full-text search engine that can run on Meteor/MongoDB server. It seems that Meteor has not developed this feature.
I wonder if there is an existing solution for adding full-text search to Meteor app.
The only thing I can find is MongoLantern, which has node.js API. How should I go about adding MongoLantern to my Meteor app?

MongoDB 2.4 will have a full text search in it. Guide can be found here.
If you are prepared to run the development releases you can download MongoDB 2.3 now - it contains text search.
Update: MongoDB 2.4 has been released. Text search is described as Beta.
The guide for text search is here and the mongod must be run like this
mongod --setParameter textSearchEnabled=true

Take a look at http://lunrjs.com/. That might also help in getting the near-instant performance of real Meteor app.

You might want to have a look at:
https://github.com/Crenshinibon/spomet
It's a Meteor native package to provide full-text search. It has an easy to include search-box with autocompletion.
You can read a tutorial about an extended example application here:
http://shiggyenterprises.wordpress.com/2013/09/28/developing-a-full-text-search-enabled-meteor-app/

There is also another way to implement a solution with Meteor. It's Search Source.
It's a kind of typeahead but without the UI part. It exposes a reactive datasource where you can use it to build the UI with Blaze as you need.
Here's a demo app: https://instant-search-demo.meteor.com/
Above app is an instant search app to search Meteor packages. How it can build with search source is documented in this article
In brief this is how search source works:
In client, create a source
var options = {
keepHistory: 1000 * 60 * 5,
localSearch: true
};
var fields = ['packageName', 'description'];
PackageSearch = new SearchSource('packages', fields, options);
Then in the server define the search source
SearchSource.defineSource('packages', function(searchText, options) {
var options = {sort: {isoScore: -1}, limit: 20};
if(searchText) {
var regExp = buildRegExp(searchText);
var selector = {packageName: regExp, description: regExp};
return Packages.find(selector, options).fetch();
} else {
return Packages.find({}, options).fetch();
}
});
function buildRegExp(searchText) {
// this is dumb implementation
var parts = searchText.trim().split(' ');
return new RegExp("(" + parts.join('|') + ")", "ig");
}
Now get the data source and render it
Template.searchResult.helpers({
getPackages: function() {
return PackageSearch.getData({
transform: function(matchText, regExp) {
return matchText.replace(regExp, "<b>$&</b>")
},
sort: {isoScore: -1}
});
}
});
Finally do the search
PackageSearch.search("the text to search");
You can learn more about how each of the above works with from the documentation.

Related

Can I use flutter to create an index on firestore?

I'm using the following flutter code to query firestore which orders the data using the field timestamp.
var results = Firestore.instance.collection('post').orderBy('timestamp').getDocuments().then((value) {
var list = value.documents;
return list.map((doc) {
return doc.documentID;
}).toList();
});
When I run this code, it throws the below exception saying an index is required:
W/Firestore(31110): (21.3.0) [Firestore]: Listen for Query(app/jQH7Fp9xCZWYiqZRe7lE/post where readAccess array_contains_any [WzKImODx6WYVqdSW3D9Az3xrUnM2, PUBLIC] order by -timestamp, -name) failed: Status{code=FAILED_PRECONDITION, description=The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/....
The exception even comes with a nice link. When opening that link, a nice UI pops up giving me the ability to create the index, with just a simple click:
Question: simple as the above may seem, I'm not very happy with this. I prefer to be able to create the index from fluttercode. In code I'm looking for something like the below:
Firestore.instance.collection('post').API-TO-CREATE-INDEX('timestamp');
Does it exist? Please advise. Many thanks.
It's not possible to create an index from client apps. You have three main choices:
Clicking the link you already saw.
Using the Firebase CLI to deploy the index from the command line.
Using the gcloud CLI to also deploy from the command line
See also the documentation on managing indexes.

I can't setup a react apollo mongodb app => resolvers with mongo / mongoose / NO METEOR

I'm currently learning Apollo, I'm a front end developer ( angular 1.5 over half a year for the background )
I have a very little experience with mongodb, and also with apollo ( trhough a meteor app )
I've read several times the Apollo doc, parsed Google with the keywords apollo, react, mongodb, resolvers, with various combinations ... ( no results )
I need to build a little React app (POC) which handle query, mutations, and subscriptions which would persist data with mongodb ( or another DB, I indicate this one since this is only one I've worked with so far ).
I cannot use Meteor.
My problem is that I can't find proper examples for graphql resolver working with mongo for all cases I need ( query, sub, mutate).
Would you have some boilerplate to provide , to help me to understand the mecanism ?
Thanks.
If you do not want to go through some tutorials. You could look at the githunt project. It is a apollo-graphql implementation with queries, mutations and subscriptions. It does not use a mongoDB, but this should be an easy change.
server: https://github.com/apollographql/GitHunt-API/tree/master/api
client: https://github.com/apollographql/GitHunt-React
Cheers
I think graphqly is the answer for you.
import graphly from "graphqly";
const gBuilder = graphly.createBuilder();
// define types, inputs ... (in any order)
gBuilder.type("Products").implements("List").def(`
products: [Product]!
`);
gBuilder.type("Product").def(`
id: ID!
name: String!
link: String
price: Int
`);
// we're too lazy to define a separate input, so we can `extend` other structure
gBuilder.input("ProductInput").ext("Product");
gBuilder.enum("ProductOrder").def(`
PRICE_DESCENDING
PRICE_ASCENDING
NEWEST
`);
// define interface `List`
gBuilder.iface("List").def(`
total: Int!,
offset: Int!,
limit: Int!,
# number of items actually in this window
size: Int!
`);
gBuilder.query(`
products(limit: Int = 20, offset: Int = 0, filter: ProductFilter): Products
`)
.resolve((root, args, context) => {
// your resolver here
// `this` is binded to the current Query instance
});
So, this is a good start for server only part with mongo / mongoose :
https://github.com/khadorkin/apollo-server-mongoose
I've enhanced this, I'll provide a link to the github repo in a few days.
Here is the repo.
Still work to be done, specially about subscriptions, but it might be a good start
Link to Github repo

Algolia Instant Search - how to not do the initial search?

I've been following the example for Algolia's Instant Search at https://www.algolia.com/doc/guides/search/instant-search/ (javascript version)
I understand that for many use-cases (like in the example) it makes sense for the script to run its initial search upon pageload and display the results (basically all results).
In my case though I'd like to not do that initial search. How can I achieve this?
Thanks
You can pass a searchFunction parameter to the instantsearch initializer, which will intercept each search and let you decide whether to perform it or not.
Here's an example taken from this Github issue. The search is not performed if the query is empty, as it will be on page load.
var search = instantsearch({
searchFunction: function(helper) {
if (helper.state.query === '') {
return;
}
helper.search();
}
});
If you have your own logic around when the search should/shouldn't be performed you can use it in here. See the Usage tab of the Initialization section of the docs for more information.

Meteor.subscribe on server side

I want to create a backend service which monitors a mongodb collection for new entries. As those are being created, I wish to run processing and update them.
I thought doing so with a Meteor service/app would be a wise idea because Meteor uses 'oplog tailing' which seems ideal for this purpose (I'd rather avoid polling if possible).
As such, I figured creating a minimal server-side-only app should solve it.
So basically, I need something along these lines:
if (Meteor.isServer) {
MyCollection = new Mongo.Collection('myCollection');
Meteor.publish('myCollectionPub', function () {
return MyCollection.find({ some: criteria... });
}
// is there such a thing?
Meteor.serverSideSubscribe('MyCollectionPub',
function (newDocs) {
// process/update newDocs
});
}
According to the Meteor docs, I cannot use Meteor.subscribe() on the server (and indeed it crashes if I try).
Question is:
Are there ways of 'subscribing' to collection updates on the server?
The PeerLibrary server-autorun package (along with it's dependant, reactive-mongo) will provide you with easy server-side observation of collections.
An alternative to #tarmes suggestion is the collection-hooks package, however as pointed out by David Weldon, it will only trigger in instance it is run in:
https://github.com/matb33/meteor-collection-hooks
MyCollection.after.insert(function (userId, doc) {
// ...
});
If you need it to run even when another instance makes a change in the mongo database, you can observe a cursor that is returned from your collection:
MyCollection.find({created_at : {$gt: some_current_time}}).observe({
added: function(item) {
// Alert code
}
});

Displaying data from mongoskin through HTML

I am using mongodb to store data and i wrote a simple js script using mongoskin to query and retrieve data from a collection and it works fine...
var db = require('mongoskin').db('winter.ceit.uq.edu.au/openbeacon');
var time = 0;
var tagid = 1101;
db.collection('set1').find({tag : {'$elemMatch': {id: tagid,name :"reader07"}}},function(err, result) {
if (err) throw err;
result.each(function(err, band) {
console.log(band.tag);
time += band.time;
});
});
However i need a way to integrate this functionality into a webpage...so say i press a button on the page, the js script runs and the queried data is displayed on the webpage. When i try using this javascript in a HTML file, it erros saying "module not found" since im referencing the index.js for mongoskin and mongodb as the source in my html file.....
Please lemme know what are the ways (preferably the simplest ways) to do this.
thank you.
Try looking for example applications
here is one
https://github.com/christkv/tic-tac-toe-steps