Skip to content

Commit ceb9b32

Browse files
author
Alex Young
committed
added full text search
1 parent 5c5fb5c commit ceb9b32

File tree

7 files changed

+105
-2
lines changed

7 files changed

+105
-2
lines changed

Jakefile.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
desc('Saves all documents to generate keywords');
3+
task('index', [], function() {
4+
app = require('./app');
5+
6+
app.Document.find({}, function(err, documents) {
7+
documents.forEach(function(d) {
8+
console.log(d._id);
9+
d.save();
10+
});
11+
});
12+
});

app.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ app.get('/documents/titles.json', loadUser, function(req, res) {
207207
[], { sort: ['title', 'descending'] },
208208
function(err, documents) {
209209
res.send(documents.map(function(d) {
210-
return { title: d.title, id: d.id };
210+
return { title: d.title, _id: d._id };
211211
}));
212212
});
213213
});
@@ -380,6 +380,21 @@ app.del('/sessions', loadUser, function(req, res) {
380380
res.redirect('/sessions/new');
381381
});
382382

383+
// Search
384+
app.post('/search.:format?', loadUser, function(req, res) {
385+
Document.find({ user_id: req.currentUser.id, keywords: req.body.s ? req.body.s : null },
386+
[], { sort: ['title', 'descending'] },
387+
function(err, documents) {
388+
switch (req.params.format) {
389+
case 'json':
390+
res.send(documents.map(function(d) {
391+
return { title: d.title, _id: d._id };
392+
}));
393+
break;
394+
}
395+
});
396+
});
397+
383398
if (!module.parent) {
384399
app.listen(3000);
385400
console.log('Express server listening on port %d, environment: %s', app.address().port, app.settings.env)

models.js

+15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ var crypto = require('crypto'),
33
User,
44
LoginToken;
55

6+
function extractKeywords(text) {
7+
if (!text) return [];
8+
9+
return text.
10+
split(/\s+/).
11+
filter(function(v) { return v.length > 2; }).
12+
filter(function(v, i, a) { return a.lastIndexOf(v) === i; });
13+
}
14+
615
function defineModels(mongoose, fn) {
716
var Schema = mongoose.Schema,
817
ObjectId = Schema.ObjectId;
@@ -14,6 +23,7 @@ function defineModels(mongoose, fn) {
1423
'title': { type: String, index: true },
1524
'data': String,
1625
'tags': [String],
26+
'keywords': [String],
1727
'user_id': ObjectId
1828
});
1929

@@ -22,6 +32,11 @@ function defineModels(mongoose, fn) {
2232
return this._id.toHexString();
2333
});
2434

35+
Document.pre('save', function(next) {
36+
this.keywords = extractKeywords(this.data);
37+
next();
38+
});
39+
2540
/**
2641
* Model: User
2742
*/

public/javascripts/application.js

+48-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121

122122
$('#create-document').click(function(e) {
123123
$.post('/documents.json', { d: { data: '', title: 'Untitled Document' } }, function(new_doc) {
124-
$('#document-list').append('<li><a id="document-title-' + new_doc._id + '" href="/documents/' + new_doc._id + '">' + new_doc.title + '</a></li>');
124+
showDocuments([new_doc]);
125125
$('#document-title-' + new_doc._id).click();
126126
});
127127
e.preventDefault();
@@ -152,6 +152,53 @@
152152
}, 5000);
153153
$('.flash').click(hideFlashMessages);
154154

155+
// Search bar
156+
function showDocuments(results) {
157+
for (var i = 0; i < results.length; i++) {
158+
$('#document-list').append('<li><a id="document-title-' + results[i]._id + '" href="/documents/' + results[i]._id + '">' + results[i].title + '</a></li>');
159+
}
160+
}
161+
162+
function search(value) {
163+
$.post('/search.json', { s: value }, function(results) {
164+
$('#document-list').html('');
165+
$('#document-list').append('<li><a id="show-all" href="#">Show All</a></li>');
166+
167+
if (results.length === 0) {
168+
alert('No results found');
169+
} else {
170+
showDocuments(results);
171+
}
172+
}, 'json');
173+
}
174+
175+
$('input[name="s"]').focus(function() {
176+
var element = $(this);
177+
if (element.val() === 'Search')
178+
element.val('');
179+
});
180+
181+
$('input[name="s"]').blur(function() {
182+
var element = $(this);
183+
if (element.val().length === 0)
184+
element.val('Search');
185+
});
186+
187+
$('form.search').submit(function(e) {
188+
search($('input[name="s"]').val());
189+
e.preventDefault();
190+
});
191+
192+
$('#show-all').live('click', function(e) {
193+
$.get('/documents/titles.json', function(results) {
194+
$('#document-list').html('');
195+
showDocuments(results);
196+
if (results.length > 0)
197+
$('#document-title-' + results[0]._id).click();
198+
});
199+
e.preventDefault();
200+
});
201+
155202
$(window).resize(resize);
156203
$(window).focus(resize);
157204
resize();

public/stylesheets/style.css

+6
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,9 @@ form.users input[type=submit] {
246246
margin-left: 140px;
247247
clear: both;
248248
}
249+
form.search {
250+
margin-right: 10px;
251+
}
252+
#show-all {
253+
color: #999;
254+
}

public/stylesheets/style.styl

+5
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,8 @@ form.users input[type=submit]
260260
margin-left 140px
261261
clear both
262262

263+
form.search
264+
margin-right 10px
265+
266+
#show-all
267+
color medium-grey

views/layout.jade

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ html
1717
- if (typeof currentUser !== 'undefined')
1818
li.right
1919
a#logout(href='/sessions') Log Out
20+
li.right
21+
form.search(action='/search')
22+
input(name='s', value='Search')
2023
!{flashMessages}
2124
!= body
2225
script(type='text/javascript', src='/javascripts/application.js')

0 commit comments

Comments
 (0)