Skip to content

Commit

Permalink
adding indexing to question dao layer (#9)
Browse files Browse the repository at this point in the history
adding basic search view at /indexSearch
  • Loading branch information
monitorjbl authored and leocwolter committed Aug 25, 2014
1 parent 7ef0211 commit 5d85144
Show file tree
Hide file tree
Showing 13 changed files with 744 additions and 29 deletions.
33 changes: 19 additions & 14 deletions src/main/java/org/mamute/controllers/QuestionController.java
Expand Up @@ -29,6 +29,7 @@
import org.mamute.model.User;
import org.mamute.model.post.PostViewCounter;
import org.mamute.model.watch.Watcher;
import org.mamute.search.QuestionIndex;
import org.mamute.util.TagsSplitter;
import org.mamute.validators.TagsValidator;
import org.mamute.vraptor.Linker;
Expand All @@ -49,6 +50,7 @@ public class QuestionController {

private Result result;
private QuestionDAO questions;
private QuestionIndex index;
private VoteDAO votes;
private LoggedUser currentUser;
private TagsValidator tagsValidator;
Expand All @@ -65,20 +67,21 @@ public class QuestionController {


/**
* @deprecated CDI eyes only
* @deprecated CDI eyes only
*/
public QuestionController() {
}

@Inject
public QuestionController(Result result, QuestionDAO questionDAO,
public QuestionController(Result result, QuestionDAO questionDAO, QuestionIndex index,
VoteDAO votes, LoggedUser currentUser, FacebookAuthService facebook,
TagsValidator tagsValidator, MessageFactory messageFactory,
Validator validator, PostViewCounter viewCounter,
Linker linker, WatcherDAO watchers, ReputationEventDAO reputationEvents,
BrutalValidator brutalValidator, TagsManager tagsManager, TagsSplitter splitter) {
this.result = result;
this.questions = questionDAO;
this.index = index;
this.votes = votes;
this.currentUser = currentUser;
this.facebook = facebook;
Expand All @@ -99,7 +102,7 @@ public QuestionController(Result result, QuestionDAO questionDAO,
@CustomBrutauthRules(LoggedRule.class)
public void questionForm() {
}

@Get
@IncludeAllTags
@CustomBrutauthRules(EditQuestionRule.class)
Expand All @@ -109,36 +112,36 @@ public void questionEditForm(@Load Question question) {

@Post
@CustomBrutauthRules(EditQuestionRule.class)
public void edit(@Load Question original, String title, String description, String tagNames,
public void edit(@Load Question original, String title, String description, String tagNames,
String comment) {

List<String> splitedTags = splitter.splitTags(tagNames);
List<Tag> loadedTags = tagsManager.findOrCreate(splitedTags);
validate(loadedTags, splitedTags);

QuestionInformation information = new QuestionInformation(title, description, this.currentUser, loadedTags, comment);
brutalValidator.validate(information);
UpdateStatus status = original.updateWith(information);

validator.onErrorUse(Results.page()).of(this.getClass()).questionEditForm(original);

result.include("editComment", comment);
result.include("question", original);

questions.save(original);
result.include("mamuteMessages",
Arrays.asList(messageFactory.build("confirmation", status.getMessage())));
result.redirectTo(this).showQuestion(original, original.getSluggedTitle());
}

@Get
public void showQuestion(@Load Question question, String sluggedTitle){
User current = currentUser.getCurrent();
if (question.isVisibleFor(current)){
result.include("markAsSolution", question.canMarkAsSolution(current));
result.include("showUpvoteBanner", !current.isVotingEnough());
result.include("editedLink", true);

redirectToRightUrl(question, sluggedTitle);
viewCounter.ping(question);
boolean isWatching = watchers.ping(question, current);
Expand All @@ -165,15 +168,17 @@ public void newQuestion(String title, String description, String tagNames, boole

List<Tag> foundTags = tagsManager.findOrCreate(splitedTags);
validate(foundTags, splitedTags);

QuestionInformation information = new QuestionInformation(title, description, currentUser, foundTags, "new question");
brutalValidator.validate(information);
User author = currentUser.getCurrent();
Question question = new Question(information, author);
result.include("question", question);
validator.onErrorRedirectTo(this).questionForm();

questions.save(question);
index.indexQuestion(question);

ReputationEvent reputationEvent = new ReputationEvent(EventType.CREATED_QUESTION, question, author);
author.increaseKarma(reputationEvent.getKarmaReward());
reputationEvents.save(reputationEvent);
Expand All @@ -190,11 +195,11 @@ public void showVoteInformation (@Load Question question, String sluggedTitle){
result.include("question", question);
redirectToRightUrl(question, sluggedTitle);
}

private boolean validate(List<Tag> foundTags, List<String> splitedTags) {
return tagsValidator.validate(foundTags, splitedTags);
}

private void redirectToRightUrl(Question question, String sluggedTitle) {
if (!question.getSluggedTitle().equals(sluggedTitle)) {
result.redirectTo(this).showQuestion(question,
Expand Down
58 changes: 48 additions & 10 deletions src/main/java/org/mamute/controllers/SearchController.java
Expand Up @@ -2,25 +2,63 @@

import javax.inject.Inject;

import org.mamute.dao.QuestionDAO;
import org.mamute.model.Question;
import org.mamute.sanitizer.HtmlSanitizer;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.environment.Environment;
import br.com.caelum.vraptor.routes.annotation.Routed;
import org.mamute.search.QuestionIndex;

import java.util.ArrayList;
import java.util.List;

@Routed
@Controller
public class SearchController {

@Inject private Result result;
@Inject private Environment env;

@Get
public void search(String query) {
String sanitized = HtmlSanitizer.sanitize(query);
result.include("customGoogleSearchKey", env.get("custom_google_search_key"));
result.include("query", sanitized);
}

@Inject
private Result result;
@Inject
private Environment env;
@Inject
private QuestionIndex index;
@Inject
private QuestionDAO dao;

@Get
public void search(String query) {
String sanitized = HtmlSanitizer.sanitize(query);
result.include("customGoogleSearchKey", env.get("custom_google_search_key"));
result.include("query", sanitized);
}

@Get
public void indexSearch(String query) {
String sanitized = HtmlSanitizer.sanitize(query);
List<Long> ids = index.findQuestionsByTitle(sanitized, 10);
List<Question> questions = new ArrayList<>();
for (Long id : ids) {
questions.add(dao.getById(id));
}

result.include("results", questions);
result.include("query", sanitized);
}

@Get
public void indexSync() {
long pages = dao.numberOfPages();
long total = 0;
for (int i = 0; i < pages; i++) {
List<Question> q = dao.allVisible(i);
index.indexQuestionBatch(q);
total += q.size();
}

result.include("total", total);
}
}
13 changes: 10 additions & 3 deletions src/main/java/org/mamute/providers/SolrServerProvider.java
Expand Up @@ -19,6 +19,7 @@

import java.io.File;

import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;

@Alternative
Expand All @@ -39,15 +40,21 @@ public SolrServerProvider(Environment env) {
public void create() {
//embedded options
Boolean embedded = Boolean.parseBoolean(env.get("solr.embedded", "false"));
String solrCore = env.get("solr.core", "mamute");
String solrHome = env.get("solr.home", "");
String solrCore = env.get("solr.core", "");


//remote options
String remoteUrl = env.get("solr.url", "");

if (embedded && isNotEmpty(solrHome)) {
if (embedded) {
LOGGER.info("Starting embedded Solr");
CoreContainer coreContainer = new CoreContainer(new File(solrHome).getAbsolutePath());
String home = solrHome;
if (isEmpty(home)) {
home = env.getResource("/solr").getPath();
}

CoreContainer coreContainer = new CoreContainer(home);
coreContainer.load();
server = new EmbeddedSolrServer(coreContainer, solrCore);
} else if (isNotEmpty(remoteUrl)) {
Expand Down
43 changes: 43 additions & 0 deletions src/main/resources/development/solr/mamute/conf/schema.xml
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
<field name="title" type="text_general" indexed="true" stored="true"/>
<field name="type" type="text_general" indexed="true" stored="true" required="true" multiValued="false"/>
<field name="tags" type="text_general" indexed="true" stored="true" required="false" multiValued="true"/>
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>

<uniqueKey>id</uniqueKey>

<copyField source="title" dest="text"/>

<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
<fieldtype name="binary" class="solr.BinaryField"/>
<fieldType name="random" class="solr.RandomSortField" indexed="true"/>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>

</schema>

0 comments on commit 5d85144

Please sign in to comment.