mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	full text search using reds, issue #142
This commit is contained in:
		| @@ -32,7 +32,8 @@ | ||||
|     "nconf": "~0.6.7", | ||||
|     "sitemap": "~0.6.0", | ||||
|     "cheerio": "~0.12.0", | ||||
|     "request": "~2.25.0" | ||||
|     "request": "~2.25.0", | ||||
|     "reds": "0.2.3" | ||||
|   }, | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/designcreateplay/NodeBB/issues" | ||||
|   | ||||
| @@ -823,3 +823,27 @@ body .navbar .nodebb-inline-block { | ||||
|   -webkit-animation: scroll-0 6s ease 0.5s infinite normal;     | ||||
|   animation: scroll-0 6s ease 0.5s infinite normal;/* Safari and Chrome: */ | ||||
| } | ||||
|  | ||||
| .form-search { | ||||
| 	float: left; | ||||
| 	margin-top: 5px; | ||||
| 	margin-bottom:0px; | ||||
| } | ||||
|  | ||||
| .search-result-post { | ||||
|   width: 100%; | ||||
|   height: 50px; | ||||
|   line-height: 16px; | ||||
|   padding: 5px; | ||||
|   overflow:hidden; | ||||
|   img { | ||||
|     display: block; | ||||
|     float: left; | ||||
|     width:48px; | ||||
|     height:48px; | ||||
|     padding-right:10px; | ||||
|   } | ||||
|   span { | ||||
|     padding-left:10px; | ||||
|   } | ||||
| } | ||||
| @@ -362,6 +362,13 @@ var socket, | ||||
|  | ||||
| 	jQuery('document').ready(function() { | ||||
| 		addTouchEvents(); | ||||
|  | ||||
| 		$('#search-form').on('submit', function() { | ||||
| 			var input = $(this).find('input'); | ||||
| 			ajaxify.go("search/"+input.val(), null, "search"); | ||||
| 			input.val(''); | ||||
| 			return false; | ||||
| 		}) | ||||
| 	}); | ||||
|  | ||||
| 	loadConfig(); | ||||
|   | ||||
| @@ -30,7 +30,8 @@ | ||||
| 		"recent": "recent", | ||||
| 		"unread": "unread", | ||||
| 		"popular": "category", | ||||
| 		"active": "category" | ||||
| 		"active": "category", | ||||
| 		"search": "search" | ||||
| 	}, | ||||
| 	"force_refresh": { | ||||
| 		"logout": true | ||||
|   | ||||
| @@ -57,6 +57,11 @@ | ||||
| 						</li> | ||||
| 					</ul> | ||||
| 					<ul id="right-menu" class="nav pull-right nodebb-inline-block"> | ||||
| 						<form id="search-form" | ||||
| 						class="form-search form-inline" action="" method="GET"> | ||||
| 							<input type="text" name="query" class="input-medium search-query"> | ||||
| 							<button type="submit" class="btn hide">Search</button> | ||||
| 						</form> | ||||
| 						<li class="notifications dropdown text-center"> | ||||
| 							<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="icon-circle-blank"></i></a> | ||||
| 							<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown"> | ||||
|   | ||||
							
								
								
									
										36
									
								
								public/templates/search.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								public/templates/search.tpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <div class="container"> | ||||
| 	<ul class="breadcrumb"> | ||||
| 		<li><a href="/">Home</a><span class="divider">/</span></li> | ||||
| 		<li class="active">Search</li> | ||||
| 	</ul> | ||||
| </div> | ||||
|  | ||||
|  | ||||
| <div class="alert alert-warning {show_no_results}" id="no-search-results"> | ||||
| 	<strong>No search results for {search_query}.</strong> | ||||
| </div> | ||||
|  | ||||
| <div class="category row"> | ||||
| 	<div class="span12"> | ||||
| 		<ul id="topics-container"> | ||||
| 		<!-- BEGIN posts --> | ||||
| 		<a href="../../topic/{posts.topicSlug}#{posts.pid}" id="tid-{posts.tid}"> | ||||
| 			<li class="category-item"> | ||||
| 				<div class="row-fluid"> | ||||
| 					<div class="span12 img-polaroid"> | ||||
| 						<div class="search-result-post"> | ||||
| 							<img src="{posts.picture}" /> | ||||
| 							<strong>{posts.username}</strong>: {posts.content} | ||||
| 						</div> | ||||
|  | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</li> | ||||
| 		</a> | ||||
| 		<!-- END posts --> | ||||
| 		</ul> | ||||
| 	</div> | ||||
| </div> | ||||
| <!-- | ||||
| <script type="text/javascript" src="{relative_path}/src/forum/search.js"></script> | ||||
| --> | ||||
| @@ -6,7 +6,9 @@ var	RDB = require('./redis.js'), | ||||
| 	async = require('async'), | ||||
| 	 | ||||
| 	utils = require('../public/src/utils'), | ||||
| 	plugins = require('./plugins'); | ||||
| 	plugins = require('./plugins'), | ||||
| 	reds = require('reds'), | ||||
| 	search = reds.createSearch('nodebbsearch'); | ||||
|  | ||||
| (function(PostTools) { | ||||
| 	PostTools.isMain = function(pid, tid, callback) { | ||||
| @@ -56,6 +58,10 @@ var	RDB = require('./redis.js'), | ||||
| 			posts.setPostField(pid, 'edited', Date.now()); | ||||
| 			posts.setPostField(pid, 'editor', uid); | ||||
|  | ||||
| 			search.remove(pid, function() { | ||||
| 				search.index(content, pid); | ||||
| 			}); | ||||
|  | ||||
| 			posts.getPostField(pid, 'tid', function(tid) { | ||||
| 				PostTools.isMain(pid, tid, function(isMainPost) { | ||||
| 					if (isMainPost)  | ||||
| @@ -84,6 +90,7 @@ var	RDB = require('./redis.js'), | ||||
| 		var success = function() { | ||||
| 			posts.setPostField(pid, 'deleted', 1); | ||||
| 			 | ||||
| 			search.remove(pid); | ||||
|  | ||||
| 			posts.getPostFields(pid, ['tid', 'uid'], function(postData) { | ||||
|  | ||||
| @@ -119,7 +126,7 @@ var	RDB = require('./redis.js'), | ||||
| 		var success = function() { | ||||
| 			posts.setPostField(pid, 'deleted', 0); | ||||
|  | ||||
| 			posts.getPostFields(pid, ['tid', 'uid'], function(postData) { | ||||
| 			posts.getPostFields(pid, ['tid', 'uid', 'content'], function(postData) { | ||||
|  | ||||
| 				user.incrementUserFieldBy(postData.uid, 'postcount', 1); | ||||
|  | ||||
| @@ -132,6 +139,8 @@ var	RDB = require('./redis.js'), | ||||
| 						topics.updateTimestamp(postData.tid, timestamp); | ||||
| 					});	 | ||||
| 				}); | ||||
|  | ||||
| 				search.index(postData.content, pid); | ||||
| 			}); | ||||
| 		}; | ||||
|  | ||||
|   | ||||
							
								
								
									
										87
									
								
								src/posts.js
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								src/posts.js
									
									
									
									
									
								
							| @@ -8,7 +8,9 @@ var	RDB = require('./redis.js'), | ||||
| 	postTools = require('./postTools'), | ||||
| 	feed = require('./feed.js'), | ||||
| 	async = require('async'), | ||||
| 	plugins = require('./plugins'); | ||||
| 	plugins = require('./plugins'), | ||||
| 	reds = require('reds'), | ||||
| 	search = reds.createSearch('nodebbsearch'); | ||||
|  | ||||
| (function(Posts) { | ||||
|  | ||||
| @@ -323,46 +325,19 @@ var	RDB = require('./redis.js'), | ||||
| 						 | ||||
| 						user.onNewPostMade(uid, tid, pid, timestamp);					 | ||||
|  | ||||
| 						var imgur = require('./imgur'); | ||||
| 						imgur.setClientID(global.nconf.get('imgurClientID')); | ||||
| 						uploadPostImages(postData, images, function(err, uploadedImages) { | ||||
| 							if(err) { | ||||
| 								console.log('Uploading images failed!'); | ||||
| 							} else { | ||||
| 								postData.uploadedImages = JSON.stringify(uploadedImages); | ||||
| 								Posts.setPostField(pid, 'uploadedImages', postData.uploadedImages); | ||||
| 							} | ||||
| 							callback(postData); | ||||
| 						}); | ||||
| 						 | ||||
| 						var uploadedImages = [];					 | ||||
|  | ||||
| 						function uploadImage(image, callback) { | ||||
| 							imgur.upload(image.data, 'base64', function(err, data) { | ||||
| 								if(err) { | ||||
| 									callback(err); | ||||
| 								} else { | ||||
| 									if(data.success) { | ||||
| 										var img= {url:data.data.link, name:image.name}; | ||||
| 										uploadedImages.push(img); | ||||
| 										callback(null); | ||||
| 									} else { | ||||
| 										callback(data); | ||||
| 									} | ||||
| 								} | ||||
| 							});			 | ||||
| 						} | ||||
|  | ||||
| 						plugins.fireHook('action:save_post_content', [pid, content]); | ||||
| 						 | ||||
| 						if(!images) { | ||||
| 							postData.uploadedImages = JSON.stringify(uploadedImages); | ||||
| 							Posts.setPostField(pid, 'uploadedImages', postData.uploadedImages); | ||||
| 							callback(postData); | ||||
| 						} else { | ||||
| 							async.each(images, uploadImage, function(err) { | ||||
| 								if(!err) { | ||||
| 									postData.uploadedImages = JSON.stringify(uploadedImages); | ||||
| 									Posts.setPostField(pid, 'uploadedImages', postData.uploadedImages); | ||||
| 		 | ||||
| 									callback(postData); | ||||
| 								} else { | ||||
| 									console.log(err); | ||||
| 									callback(null); | ||||
| 								} | ||||
| 							}); | ||||
| 						} | ||||
| 						search.index(content, pid); | ||||
| 					}); | ||||
| 				}); | ||||
| 			} else { | ||||
| @@ -370,6 +345,42 @@ var	RDB = require('./redis.js'), | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	function uploadPostImages(postData, images, callback) { | ||||
| 		var imgur = require('./imgur'); | ||||
| 		imgur.setClientID(global.nconf.get('imgurClientID')); | ||||
| 						 | ||||
| 		var uploadedImages = [];					 | ||||
|  | ||||
| 		function uploadImage(image, callback) { | ||||
| 			imgur.upload(image.data, 'base64', function(err, data) { | ||||
| 				if(err) { | ||||
| 					callback(err); | ||||
| 				} else { | ||||
| 					if(data.success) { | ||||
| 						var img= {url:data.data.link, name:image.name}; | ||||
| 						uploadedImages.push(img); | ||||
| 						callback(null); | ||||
| 					} else { | ||||
| 						callback(data); | ||||
| 					} | ||||
| 				} | ||||
| 			});			 | ||||
| 		} | ||||
|  | ||||
| 		if(!images) { | ||||
| 			callback(null, uploadedImages); | ||||
| 		} else { | ||||
| 			async.each(images, uploadImage, function(err) { | ||||
| 				if(!err) { | ||||
| 					callback(null, uploadedImages); | ||||
| 				} else { | ||||
| 					console.log(err); | ||||
| 					callback(err, null); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	Posts.getPostsByUid = function(uid, start, end, callback) { | ||||
| 		 | ||||
|   | ||||
| @@ -146,5 +146,36 @@ var user = require('./../user.js'), | ||||
| 				res.redirect(global.nconf.get('relative_path') + '/404'); | ||||
| 			} | ||||
| 		});	 | ||||
|  | ||||
| 		app.get('/api/search', function(req, res) { | ||||
| 			return res.json({ | ||||
| 				show_no_results:'hide', | ||||
| 				search_query:'', | ||||
| 				posts:[] | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		app.get('/api/search/:term', function(req, res, next) { | ||||
|  | ||||
| 			var reds = require('reds'); | ||||
| 			var search = reds.createSearch('nodebbsearch'); | ||||
| 		 | ||||
| 			search | ||||
| 				.query(query = req.params.term).type('or') | ||||
| 				.end(function(err, ids) { | ||||
| 					if (err)  | ||||
| 						return next(); | ||||
| 					 | ||||
| 					 | ||||
| 					posts.getPostSummaryByPids(ids, function(posts) { | ||||
| 						res.json(200, { | ||||
| 							show_no_results:ids.length?'hide':'show', | ||||
| 							search_query:req.params.term, | ||||
| 							posts:posts | ||||
| 						});						 | ||||
| 					}); | ||||
| 	 | ||||
| 				}); | ||||
| 		}); | ||||
| 	} | ||||
| }(exports)); | ||||
|   | ||||
| @@ -382,6 +382,18 @@ var express = require('express'), | ||||
| 				res.redirect(global.nconf.get('relative_path') + '/404'); | ||||
| 			} | ||||
| 		});		 | ||||
|  | ||||
| 		app.get('/search', function(req, res) { | ||||
| 			app.build_header({ req: req, res: res }, function(err, header) { | ||||
| 				res.send(header + app.create_route("search", null, "search") + templates['footer']); | ||||
| 			}); | ||||
| 		}); | ||||
| 		 | ||||
| 		app.get('/search/:term', function(req, res) { | ||||
| 			app.build_header({ req: req, res: res }, function(err, header) { | ||||
| 				res.send(header + app.create_route("search/"+req.params.term, null, "search") + templates['footer']); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
|  | ||||
| }(WebServer)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user