Author: bpoussin Date: 2011-12-29 13:06:50 +0100 (Thu, 29 Dec 2011) New Revision: 1262 Url: http://nuiton.org/repositories/revision/wikitty/1262 Log: Evolution #1863: Create new query api with visitor and better implementation Evolution #1864: Add query langage syntaxe Debut d'implantation dans le module Solr ('plus que' le visiteur a implanter) Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/FacetQuery.java trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java Added: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/FacetQuery.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/FacetQuery.java (rev 0) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/FacetQuery.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -0,0 +1,38 @@ +package org.nuiton.wikitty.query; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.wikitty.query.conditions.Condition; + +/** + * Contient une Condition pour creer une facet dans un {@link WikittyQuery} + * + * @author poussin + * @version $Revision$ + * @since 3.3 + * + * Last update: $Date$ + * by : $Author$ + */ +public class FacetQuery { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(FacetQuery.class); + + protected String name; + protected Condition condition; + + public FacetQuery(String name, Condition condition) { + this.name = name; + this.condition = condition; + } + + public String getName() { + return name; + } + + public Condition getCondition() { + return condition; + } + +} Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java 2011-12-28 18:55:40 UTC (rev 1261) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQuery.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -64,7 +64,7 @@ protected int facetLimit = 100; /** Facet on condition. */ - protected List<Condition> facetCriteria; + protected List<FacetQuery> facetQuery; /** Facet on field. */ protected List<String> facetField; /** if true facet is done on extension name */ @@ -115,7 +115,7 @@ ObjectUtils.equals(this.getSortDescending(), other.getSortDescending()) && ObjectUtils.equals(this.getFacetLimit(), other.getFacetLimit()) && ObjectUtils.equals(this.getFacetMinCount(), other.getFacetMinCount()) && - ObjectUtils.equals(this.getFacetCriteria(), other.getFacetCriteria()) && + ObjectUtils.equals(this.getFacetQuery(), other.getFacetQuery()) && ObjectUtils.equals(this.getCondition(), other.getCondition()); } else { result = false; @@ -210,23 +210,28 @@ return this; } - public List<Condition> getFacetCriteria() { - if (facetCriteria == null) { - facetCriteria = new LinkedList<Condition>(); + public List<FacetQuery> getFacetQuery() { + if (facetQuery == null) { + facetQuery = new LinkedList<FacetQuery>(); } - return facetCriteria; + return facetQuery; } - public WikittyQuery addFacetCriteria(Condition criteria) { - getFacetCriteria().add(criteria); + public WikittyQuery addFacetQuery(FacetQuery facetQuery) { + getFacetQuery().add(facetQuery); return this; } - public WikittyQuery setFacetCriteria(Condition ... facetCriteria) { - this.facetCriteria = new LinkedList<Condition>(Arrays.asList(facetCriteria)); + public WikittyQuery addFacetQuery(String name, Condition condition) { + getFacetQuery().add(new FacetQuery(name, condition)); return this; } + public WikittyQuery setFacetQuery(FacetQuery ... facetQuery) { + this.facetQuery = new LinkedList<FacetQuery>(Arrays.asList(facetQuery)); + return this; + } + public List<String> getFacetField() { if (facetField == null) { facetField = new LinkedList<String>(); Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java 2011-12-28 18:55:40 UTC (rev 1261) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryMaker.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -181,6 +181,18 @@ } /** + * Ajoute une condition, cette condition est prise comme une condition terminal + * Si l'on veut continuer a construire la requete, il faut avoir ajouter + * avant une {@link #and()}, {@link #or()}, {@link #not()}, {@link #join()} + * @param c la condition a ajouter + * @return {@code this} with the {@code c} restriction added. + */ + public WikittyQueryMaker condition(Condition c) { + addCondition(c); + return this; + } + + /** * Contains. * * Search on lists (multivalued fields) that a field contains all the values Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java 2011-12-28 18:55:40 UTC (rev 1261) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/query/WikittyQueryVisitorCopy.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -55,6 +55,11 @@ return result; } + public Condition getCondition() { + Condition result = getQueryMaker().getCondition(); + return result; + } + @Override public boolean visitEnter(WikittyQuery o) { WikittyQuery q = getQuery(); @@ -68,11 +73,11 @@ q.setSortAscending(new ArrayList<String>(o.getSortAscending())); q.setSortDescending(new ArrayList<String>(o.getSortDescending())); - for (Condition c : o.getFacetCriteria()) { + for (FacetQuery c : o.getFacetQuery()) { WikittyQueryVisitorCopy v = new WikittyQueryVisitorCopy(); - c.accept(v); - Condition facetCriteria = v.getQueryMaker().getCondition(); - q.addFacetCriteria(facetCriteria); + c.getCondition().accept(v); + Condition condition = v.getCondition(); + q.addFacetQuery(c.getName(), condition); } return true; } Added: trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java =================================================================== --- trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java (rev 0) +++ trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittyQueryVisitorToSolr.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -0,0 +1,222 @@ +package org.nuiton.wikitty.storage.solr; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.solr.client.solrj.SolrServer; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryVisitor; +import org.nuiton.wikitty.query.conditions.And; +import org.nuiton.wikitty.query.conditions.Between; +import org.nuiton.wikitty.query.conditions.Condition; +import org.nuiton.wikitty.query.conditions.ContainsAll; +import org.nuiton.wikitty.query.conditions.ContainsOne; +import org.nuiton.wikitty.query.conditions.Equals; +import org.nuiton.wikitty.query.conditions.False; +import org.nuiton.wikitty.query.conditions.Greater; +import org.nuiton.wikitty.query.conditions.GreaterOrEquals; +import org.nuiton.wikitty.query.conditions.Join; +import org.nuiton.wikitty.query.conditions.Keyword; +import org.nuiton.wikitty.query.conditions.Less; +import org.nuiton.wikitty.query.conditions.LessOrEquals; +import org.nuiton.wikitty.query.conditions.Like; +import org.nuiton.wikitty.query.conditions.Not; +import org.nuiton.wikitty.query.conditions.NotEquals; +import org.nuiton.wikitty.query.conditions.NotNull; +import org.nuiton.wikitty.query.conditions.Null; +import org.nuiton.wikitty.query.conditions.Or; +import org.nuiton.wikitty.query.conditions.True; +import org.nuiton.wikitty.query.conditions.Unlike; + +/** + * Converti une {@link Condition} en une requete Solr, une fois la condition + * converti on peut la recuperer par {@link #getSolrQuery()}. + * + * Cette objet ne peut etre utiliser qu'un seul fois, il faut creer un nouveau + * visiteur pour chaque convertion. + * + * @author poussin + * @version $Revision$ + * @since 3.3 + * + * Last update: $Date$ + * by : $Author$ + */ +class WikittyQueryVisitorToSolr extends WikittyQueryVisitor { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(WikittyQueryVisitorToSolr.class); + + protected SolrServer solrServer; + protected FieldModifier fieldModifier; + + protected String solrQuery = ""; + + public String getSolrQuery() { + return solrQuery; + } + + public WikittyQueryVisitorToSolr(SolrServer solrServer, FieldModifier fieldModifier) { + this.solrServer = solrServer; + this.fieldModifier = fieldModifier; + } + + @Override + public boolean visitEnter(WikittyQuery o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visitLeave(WikittyQuery o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitEnter(And o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitMiddle(And o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visitLeave(And o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitEnter(Or o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitMiddle(Or o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visitLeave(Or o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitEnter(Join o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visitLeave(Join o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean visitEnter(Not o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visitLeave(Not o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Between o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(ContainsAll o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(ContainsOne o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Equals o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(NotEquals o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(False o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(True o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Greater o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(GreaterOrEquals o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Keyword o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Less o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(LessOrEquals o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Like o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Unlike o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(Null o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(NotNull o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void defaultVisit(Object o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean defaultVisitEnter(Object o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean defaultVisitMiddle(Object o) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void defaultVisitLeave(Object o, boolean enterOrMiddleResult) { + throw new UnsupportedOperationException("Not supported yet."); + } +} Modified: trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java =================================================================== --- trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java 2011-12-28 18:55:40 UTC (rev 1261) +++ trunk/wikitty-solr/src/main/java/org/nuiton/wikitty/storage/solr/WikittySearchEngineSolr.java 2011-12-29 12:06:50 UTC (rev 1262) @@ -49,7 +49,6 @@ import org.apache.solr.common.SolrInputDocument; import org.apache.solr.core.CoreContainer; import org.nuiton.wikitty.search.Criteria; -import org.nuiton.wikitty.search.FacetTopic; import org.nuiton.wikitty.entities.FieldType; import org.nuiton.wikitty.entities.FieldType.TYPE; import org.nuiton.wikitty.search.PagedResult; @@ -67,6 +66,12 @@ import org.nuiton.wikitty.WikittyConfigOption; import org.nuiton.wikitty.WikittyUtil; import org.nuiton.wikitty.entities.WikittyTreeNodeHelper; +import org.nuiton.wikitty.query.FacetQuery; +import org.nuiton.wikitty.query.FacetTopic; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; +import org.nuiton.wikitty.query.WikittyQueryResultTreeNode; import org.nuiton.wikitty.search.Search; import org.nuiton.wikitty.search.TreeNodeResult; @@ -643,94 +648,93 @@ } @Override - public PagedResult<String> findAllByCriteria(WikittyTransaction transaction, Criteria criteria) { + public WikittyQueryResult<String> findAllByQuery(WikittyTransaction transaction, WikittyQuery query) { try { - // Create query with restriction - Restriction2Solr restriction2Solr = new Restriction2Solr(transaction, fieldModifier); - String queryString = restriction2Solr.toSolr(criteria.getRestriction(), solrServer); - SolrQuery query = new SolrQuery(SOLR_QUERY_PARSER + queryString); + // Create querySolr + WikittyQueryVisitorToSolr v = new WikittyQueryVisitorToSolr(solrServer, fieldModifier); + query.getCondition().accept(v); + String queryString = v.getSolrQuery(); + SolrQuery querySolr = new SolrQuery(SOLR_QUERY_PARSER + queryString); // Add paged - int firstIndex = criteria.getFirstIndex(); - int endIndex = criteria.getEndIndex(); + int first = query.getFirst(); + int limit = query.getLimit(); - query.setStart(firstIndex); - int nbRows; - if (endIndex == -1) { + if (limit == Integer.MAX_VALUE) { // WARNING It is necessary to substract 'start' otherwise, // there is a capacity overlow in solR - nbRows = Integer.MAX_VALUE - firstIndex; - } else { - nbRows = endIndex - firstIndex + 1; + limit = Integer.MAX_VALUE - first; } - query.setRows(nbRows); + querySolr.setStart(first); + querySolr.setRows(limit); // Add sorting - List<String> sortAscending = criteria.getSortAscending(); + List<String> sortAscending = query.getSortAscending(); if(sortAscending != null) { for (String sort : sortAscending) { String tranform = fieldModifier.convertToSolr(transaction, sort); tranform += WikittySolrConstant.SUFFIX_SORTABLE; - query.addSortField(tranform, SolrQuery.ORDER.asc); + querySolr.addSortField(tranform, SolrQuery.ORDER.asc); } } - List<String> sortDescending = criteria.getSortDescending(); + List<String> sortDescending = query.getSortDescending(); if(sortDescending != null) { for (String sort : sortDescending) { String tranform = fieldModifier.convertToSolr(transaction, sort); tranform += WikittySolrConstant.SUFFIX_SORTABLE; - query.addSortField(tranform, SolrQuery.ORDER.desc); + querySolr.addSortField(tranform, SolrQuery.ORDER.desc); } } // task : #1785 Add select method to allow specify wikittyId return field // If select is not empty, add facet on field - String select = criteria.getSelect(); + String select = query.getSelect(); boolean hasSelect = StringUtils.isNotEmpty(select); if (hasSelect) { // Limit on wikitty String selectWikitty = SolrUtil.getSolrFieldName(select, TYPE.WIKITTY); - criteria.addFacetField(selectWikitty); + query.addFacetField(selectWikitty); // We need no result, just facet - criteria.setEndIndex(firstIndex); + query.setLimit(0); } // Add faceting - List<String> facetField = criteria.getFacetField(); - List<Criteria> facetCriteria = criteria.getFacetCriteria(); + List<String> facetField = query.getFacetField(); + List<FacetQuery> facetQuery = query.getFacetQuery(); // use to map query string to criteria facet name Map<String, String> facetQueryToName = new HashMap<String, String>(); if ((facetField != null && !facetField.isEmpty()) - || (facetCriteria != null && !facetCriteria.isEmpty())) { - query.setFacet(true); - query.setFacetMinCount(criteria.getFacetMinCount()); - query.setFacetLimit(criteria.getFacetLimit()); + || (facetQuery != null && !facetQuery.isEmpty())) { + querySolr.setFacet(true); + querySolr.setFacetMinCount(query.getFacetMinCount()); + querySolr.setFacetLimit(query.getFacetLimit()); // field facetisation if (facetField != null) { for (String fqfieldName : facetField) { String tranform = fieldModifier.convertToSolr(transaction, fqfieldName); - query.addFacetField(tranform); + querySolr.addFacetField(tranform); } } // query facetisation - if (facetCriteria != null) { - for (Criteria facet : facetCriteria) { - String queryFacet = - restriction2Solr.toSolr(facet.getRestriction(), solrServer); + if (facetQuery != null) { + for (FacetQuery facet : facetQuery) { + v = new WikittyQueryVisitorToSolr(solrServer, fieldModifier); + facet.getCondition().accept(v); + String queryFacet = v.getSolrQuery(); facetQueryToName.put(queryFacet, facet.getName()); - query.addFacetQuery(queryFacet); + querySolr.addFacetQuery(queryFacet); } } } - QueryResponse resp = SolrUtil.executeQuery(solrServer, query); + QueryResponse resp = SolrUtil.executeQuery(solrServer, querySolr); SolrDocumentList solrResults = resp.getResults(); Map<String, List<FacetTopic>> facets = new HashMap<String, List<FacetTopic>>(); @@ -749,7 +753,7 @@ facets.put(facetName, topics); } } - if (facetCriteria != null && !facetCriteria.isEmpty()) { + if (facetQuery != null && !facetQuery.isEmpty()) { for (Map.Entry<String, Integer> facet : resp.getFacetQuery().entrySet()) { String facetName = facet.getKey(); // don't use contains because, map can have key with null value @@ -780,10 +784,8 @@ // Extract ids starting on firstIndex ids = new ArrayList<String>(); - // If all must be return, use nbRows - endIndex = (endIndex == -1 ? nbRows : endIndex); - for (int i = firstIndex;i <= endIndex && i < numFound;i++) { - + // If all must be return, use limit + for (int i = first;i <= limit && i < numFound; i++) { FacetTopic topic = facetTopics.get(i); ids.add(topic.getTopicName()); } @@ -803,14 +805,14 @@ } // Build paged result - PagedResult<String> result = new PagedResult<String>( - criteria.getName(), - firstIndex, numFound, queryString, facets, ids); + WikittyQueryResult<String> result = new WikittyQueryResult<String>( + query.getName(), + first, numFound, queryString, facets, ids); return result; } catch (SolrServerException eee) { throw new WikittyException(String.format( - "Error during find of criteria '%s'", criteria), eee); + "Error during find of query '%s'", query), eee); } } @@ -826,34 +828,34 @@ * @return all childrens count */ @Override - public TreeNodeResult<String> findAllChildrenCount( + public WikittyQueryResultTreeNode<String> findAllChildrenCount( WikittyTransaction transaction, - String wikittyId, int depth, boolean count, Criteria filter) { + String wikittyId, int depth, boolean count, WikittyQuery filter) { try { - TreeNodeResult<String> result = null; + WikittyQueryResultTreeNode<String> result = null; SolrDocument doc = SolrUtil.findById(solrServer, wikittyId); if (doc != null) { // on verifie que l'argument est bien un TreeNode if (doc.containsKey(TREENODE_DEPTH)) { - Search treeSearch = Search.query().and().eq(TREENODE_PARENTS, wikittyId); + WikittyQueryMaker treeSearch = new WikittyQueryMaker() + .and().eq(TREENODE_PARENTS, wikittyId); if (depth >= 0) { Integer d = SolrUtil.getIntFieldValue(doc, TREENODE_DEPTH); - treeSearch = treeSearch.bw(TREENODE_DEPTH, - String.valueOf(d), - String.valueOf(d + depth)); + treeSearch = treeSearch.bw(TREENODE_DEPTH, d, d + depth); } - Criteria treeCriteria = treeSearch.criteria(); + WikittyQuery treeQuery = treeSearch.getQuery(); // on a dans treeSearch uniquement le noeud passe en parametre // et ses enfants jusqu'a la profondeur demandee - Restriction2Solr restriction2Solr = - new Restriction2Solr(transaction, fieldModifier); - String queryString = restriction2Solr.toSolr( - treeCriteria.getRestriction(), solrServer); - SolrQuery query = new SolrQuery(SOLR_QUERY_PARSER + queryString); - QueryResponse resp = SolrUtil.executeQuery(solrServer, query); + // Create querySolr + WikittyQueryVisitorToSolr v = new WikittyQueryVisitorToSolr(solrServer, fieldModifier); + treeQuery.getCondition().accept(v); + String queryString = v.getSolrQuery(); + SolrQuery querySolr = new SolrQuery(SOLR_QUERY_PARSER + queryString); + + QueryResponse resp = SolrUtil.executeQuery(solrServer, querySolr); SolrDocumentList solrResults = resp.getResults(); Map<String, Integer> counts = new HashMap<String, Integer>(); @@ -862,12 +864,17 @@ // TODO poussin 20110128 regarder si on ne peut pas // restreindre les facettes aux noeuds trouve dans la recherche // precedente - Criteria attCriteria = Search.query(filter).eq( - TREENODE_ATTACHED_ALL, wikittyId).criteria() - .setFirstIndex(0).setEndIndex(0) - .addFacetField(TREENODE_ATTACHED_ALL); - PagedResult<String> attSearch = - findAllByCriteria(transaction, attCriteria); + WikittyQuery attQuery = new WikittyQueryMaker() + .and().condition(filter.getCondition()) + .eq(TREENODE_ATTACHED_ALL, wikittyId).end() + .setFirst(0).setLimit(0) + .addFacetField(TREENODE_ATTACHED_ALL) + // l'arbre peut avoir beaucoup de branche, il + // faut que toutes les branches aient un count + // des attachments + .setFacetLimit(Integer.MAX_VALUE); + WikittyQueryResult<String> attSearch = + findAllByQuery(transaction, attQuery); List<FacetTopic> topics = attSearch.getTopic(TREENODE_ATTACHED_ALL); if (topics != null) { for (FacetTopic topic : topics) { @@ -881,8 +888,8 @@ // construction du resultat, il proceder en 2 phases car // sinon si on construit un fils avant son pere, il ne sera // jamais associe - Map<String, TreeNodeResult<String>> allTreeNodeResult = - new HashMap<String, TreeNodeResult<String>>(); + Map<String, WikittyQueryResultTreeNode<String>> allTreeNodeResult = + new HashMap<String, WikittyQueryResultTreeNode<String>>(); // key: id de l'enfant, value: l'id du parent Map<String, String> childParent = new HashMap<String, String>(); // construction de tous les TreeNodeResult qui permettront @@ -894,17 +901,18 @@ WikittyTreeNode.FQ_FIELD_WIKITTYTREENODE_PARENT, TYPE.WIKITTY); int nb = counts.containsKey(id) ? counts.get(id) : 0; - TreeNodeResult<String> child = new TreeNodeResult<String>(id, nb); + WikittyQueryResultTreeNode<String> child = + new WikittyQueryResultTreeNode<String>(id, nb); allTreeNodeResult.put(id, child); childParent.put(id, parentId); } // construction de l'arbre avant de le retourner - for(Map.Entry<String, TreeNodeResult<String>> e : allTreeNodeResult.entrySet()) { + for(Map.Entry<String, WikittyQueryResultTreeNode<String>> e : allTreeNodeResult.entrySet()) { String id = e.getKey(); String parentId = childParent.get(id); if (allTreeNodeResult.containsKey(parentId)) { - TreeNodeResult<String> child = e.getValue(); - TreeNodeResult<String> parent = allTreeNodeResult.get(parentId); + WikittyQueryResultTreeNode<String> child = e.getValue(); + WikittyQueryResultTreeNode<String> parent = allTreeNodeResult.get(parentId); if (parent != child) { parent.add(child); } @@ -1054,4 +1062,288 @@ solrCore.shutdown(); } + + + @Override + public PagedResult<String> findAllByCriteria(WikittyTransaction transaction, Criteria criteria) { + try { + // Create query with restriction + Restriction2Solr restriction2Solr = new Restriction2Solr(transaction, fieldModifier); + String queryString = restriction2Solr.toSolr(criteria.getRestriction(), solrServer); + SolrQuery query = new SolrQuery(SOLR_QUERY_PARSER + queryString); + + // Add paged + int firstIndex = criteria.getFirstIndex(); + int endIndex = criteria.getEndIndex(); + + query.setStart(firstIndex); + int nbRows; + if (endIndex == -1) { + // WARNING It is necessary to substract 'start' otherwise, + // there is a capacity overlow in solR + nbRows = Integer.MAX_VALUE - firstIndex; + } else { + nbRows = endIndex - firstIndex + 1; + } + query.setRows(nbRows); + + // Add sorting + List<String> sortAscending = criteria.getSortAscending(); + if(sortAscending != null) { + for (String sort : sortAscending) { + String tranform = fieldModifier.convertToSolr(transaction, sort); + tranform += WikittySolrConstant.SUFFIX_SORTABLE; + query.addSortField(tranform, SolrQuery.ORDER.asc); + } + } + + List<String> sortDescending = criteria.getSortDescending(); + if(sortDescending != null) { + for (String sort : sortDescending) { + String tranform = fieldModifier.convertToSolr(transaction, sort); + tranform += WikittySolrConstant.SUFFIX_SORTABLE; + query.addSortField(tranform, SolrQuery.ORDER.desc); + } + } + + // task : #1785 Add select method to allow specify wikittyId return field + // If select is not empty, add facet on field + String select = criteria.getSelect(); + boolean hasSelect = StringUtils.isNotEmpty(select); + if (hasSelect) { + + // Limit on wikitty + String selectWikitty = SolrUtil.getSolrFieldName(select, TYPE.WIKITTY); + criteria.addFacetField(selectWikitty); + + // We need no result, just facet + criteria.setEndIndex(firstIndex); + } + + // Add faceting + List<String> facetField = criteria.getFacetField(); + List<Criteria> facetCriteria = criteria.getFacetCriteria(); + + // use to map query string to criteria facet name + Map<String, String> facetQueryToName = new HashMap<String, String>(); + + if ((facetField != null && !facetField.isEmpty()) + || (facetCriteria != null && !facetCriteria.isEmpty())) { + query.setFacet(true); + query.setFacetMinCount(criteria.getFacetMinCount()); + query.setFacetLimit(criteria.getFacetLimit()); + + // field facetisation + if (facetField != null) { + for (String fqfieldName : facetField) { + String tranform = fieldModifier.convertToSolr(transaction, fqfieldName); + query.addFacetField(tranform); + } + } + + // query facetisation + if (facetCriteria != null) { + for (Criteria facet : facetCriteria) { + String queryFacet = + restriction2Solr.toSolr(facet.getRestriction(), solrServer); + facetQueryToName.put(queryFacet, facet.getName()); + query.addFacetQuery(queryFacet); + } + } + } + + QueryResponse resp = SolrUtil.executeQuery(solrServer, query); + SolrDocumentList solrResults = resp.getResults(); + + Map<String, List<org.nuiton.wikitty.search.FacetTopic>> facets = new HashMap<String, List<org.nuiton.wikitty.search.FacetTopic>>(); + if (facetField != null && !facetField.isEmpty()) { + for (FacetField facet : resp.getFacetFields()) { + String facetName = fieldModifier.convertToField(transaction, facet.getName()); + List<org.nuiton.wikitty.search.FacetTopic> topics = new ArrayList<org.nuiton.wikitty.search.FacetTopic>(); + if (facet.getValues() != null) { + for (FacetField.Count value : facet.getValues()) { + String topicName = value.getName(); + int topicCount = (int) value.getCount(); + org.nuiton.wikitty.search.FacetTopic topic = new org.nuiton.wikitty.search.FacetTopic(facetName, topicName, topicCount); + topics.add(topic); + } + } + facets.put(facetName, topics); + } + } + if (facetCriteria != null && !facetCriteria.isEmpty()) { + for (Map.Entry<String, Integer> facet : resp.getFacetQuery().entrySet()) { + String facetName = facet.getKey(); + // don't use contains because, map can have key with null value + if (null != facetQueryToName.get(facetName)) { + facetName = facetQueryToName.get(facetName); + } + Integer count = facet.getValue(); + List<org.nuiton.wikitty.search.FacetTopic> topics = new ArrayList<org.nuiton.wikitty.search.FacetTopic>(); + org.nuiton.wikitty.search.FacetTopic topic = new org.nuiton.wikitty.search.FacetTopic(facetName, facetName, count); + topics.add(topic); + facets.put(facetName, topics); + } + } + + List<String> ids; + int numFound; + if (hasSelect) { + + // Get select facet + List<org.nuiton.wikitty.search.FacetTopic> facetTopics = facets.get(select); + + // Remove this one + facets.remove(select); + + // Total found + numFound = facetTopics.size(); + + // Extract ids starting on firstIndex + ids = new ArrayList<String>(); + + // If all must be return, use nbRows + endIndex = (endIndex == -1 ? nbRows : endIndex); + for (int i = firstIndex;i <= endIndex && i < numFound;i++) { + + org.nuiton.wikitty.search.FacetTopic topic = facetTopics.get(i); + ids.add(topic.getTopicName()); + } + + } else { + + // Extract ids + ids = new ArrayList<String>(solrResults.size()); + for (SolrDocument doc : solrResults) { + + String id = SolrUtil.getStringFieldValue(doc, SOLR_ID); + ids.add(id); + } + + // Get total num found + numFound = (int)resp.getResults().getNumFound(); + } + + // Build paged result + PagedResult<String> result = new PagedResult<String>( + criteria.getName(), + firstIndex, numFound, queryString, facets, ids); + + return result; + } catch (SolrServerException eee) { + throw new WikittyException(String.format( + "Error during find of criteria '%s'", criteria), eee); + } + } + + /** + * Si l'argument n'est pas un TreeNode, une exception est levee + * + * @param transaction wikitty transaction + * @param wikittyId l'objet root du resultat + * @param depth profondeur souhaite pour la recherche des fils + * @param count vrai si l'on souhaite avoir le nombre d'attachment associe + * au noeud retourne + * @param filter filtre utilise pour compter le nombre d'attachment + * @return all childrens count + */ + @Override + public TreeNodeResult<String> findAllChildrenCount( + WikittyTransaction transaction, + String wikittyId, int depth, boolean count, Criteria filter) { + try { + TreeNodeResult<String> result = null; + + SolrDocument doc = SolrUtil.findById(solrServer, wikittyId); + if (doc != null) { + // on verifie que l'argument est bien un TreeNode + if (doc.containsKey(TREENODE_DEPTH)) { + + Search treeSearch = Search.query().and().eq(TREENODE_PARENTS, wikittyId); + if (depth >= 0) { + Integer d = SolrUtil.getIntFieldValue(doc, TREENODE_DEPTH); + treeSearch = treeSearch.bw(TREENODE_DEPTH, + String.valueOf(d), + String.valueOf(d + depth)); + } + Criteria treeCriteria = treeSearch.criteria(); + + // on a dans treeSearch uniquement le noeud passe en parametre + // et ses enfants jusqu'a la profondeur demandee + Restriction2Solr restriction2Solr = + new Restriction2Solr(transaction, fieldModifier); + String queryString = restriction2Solr.toSolr( + treeCriteria.getRestriction(), solrServer); + SolrQuery query = new SolrQuery(SOLR_QUERY_PARSER + queryString); + QueryResponse resp = SolrUtil.executeQuery(solrServer, query); + SolrDocumentList solrResults = resp.getResults(); + + Map<String, Integer> counts = new HashMap<String, Integer>(); + // recuperation si demande du nombre d'attachment par noeud + if (count) { + // TODO poussin 20110128 regarder si on ne peut pas + // restreindre les facettes aux noeuds trouve dans la recherche + // precedente + Criteria attCriteria = Search.query(filter).eq( + TREENODE_ATTACHED_ALL, wikittyId).criteria() + .setFirstIndex(0).setEndIndex(0) + .addFacetField(TREENODE_ATTACHED_ALL); + PagedResult<String> attSearch = + findAllByCriteria(transaction, attCriteria); + List<org.nuiton.wikitty.search.FacetTopic> topics = attSearch.getTopic(TREENODE_ATTACHED_ALL); + if (topics != null) { + for (org.nuiton.wikitty.search.FacetTopic topic : topics) { + String topicName = topic.getTopicName(); + int topicCount = topic.getCount(); + counts.put(topicName, topicCount); + } + } + } + + // construction du resultat, il proceder en 2 phases car + // sinon si on construit un fils avant son pere, il ne sera + // jamais associe + Map<String, TreeNodeResult<String>> allTreeNodeResult = + new HashMap<String, TreeNodeResult<String>>(); + // key: id de l'enfant, value: l'id du parent + Map<String, String> childParent = new HashMap<String, String>(); + // construction de tous les TreeNodeResult qui permettront + // de construire l'arbre + for (SolrDocument d : solrResults) { + String id = SolrUtil.getStringFieldValue(d, SOLR_ID); + + String parentId = SolrUtil.getStringFieldValue(d, + WikittyTreeNode.FQ_FIELD_WIKITTYTREENODE_PARENT, + TYPE.WIKITTY); + int nb = counts.containsKey(id) ? counts.get(id) : 0; + TreeNodeResult<String> child = new TreeNodeResult<String>(id, nb); + allTreeNodeResult.put(id, child); + childParent.put(id, parentId); + } + // construction de l'arbre avant de le retourner + for(Map.Entry<String, TreeNodeResult<String>> e : allTreeNodeResult.entrySet()) { + String id = e.getKey(); + String parentId = childParent.get(id); + if (allTreeNodeResult.containsKey(parentId)) { + TreeNodeResult<String> child = e.getValue(); + TreeNodeResult<String> parent = allTreeNodeResult.get(parentId); + if (parent != child) { + parent.add(child); + } + } + } + result = allTreeNodeResult.get(wikittyId); + } else { + throw new WikittyException(String.format( + "Wikitty '%s' do not handle extension %s", + wikittyId, WikittyTreeNode.EXT_WIKITTYTREENODE)); + } + } + return result; + } catch (SolrServerException eee) { + throw new WikittyException("Error during find", eee); + } + + } + }