void ResultCollectorImpl::collect(const QueryResult& queryResults) { if (queryResults.hasError()) { m_result.setError(m_result.getErrorMsg() + queryResults.getErrorMsg()); } else { m_result.setTotalHits(m_result.getTotalHits() + queryResults.getTotalHits()); if (queryResults.getTimeCost() > m_result.getTimeCost()) { m_result.setTimeCost(queryResults.getTimeCost()); } shardid_t shardId = -1; QueryResult::Iterator it = queryResults.iterator(); while (it.hasNext()) { const ResultDocPtr& pDoc = it.next(); m_pResultQueue->insert(pDoc); shardId = pDoc->getShardId(); } const QueryTracerPtr& pTracer = queryResults.getTracer(); if (pTracer.isNotNull()) { if (m_result.getTracer().isNull()) { m_result.setTracer(new QueryTracer("proxy", pTracer->getLevel())); } QueryTracerPtr& pResTracer = m_result.getTracer(); string str; NumberFormatter::append(str, shardId); pResTracer->addChildTracer(pTracer)->prependPath(str); } } }
void SearchShardsBase::collectPhaseTwoResult() { FX_DEBUG("Collect phase two result"); SEARCH_LATENCY_BEGIN(); QueryResult phaseTwoResult; const QueryResult& qResult = m_pResultCollector->getResult(); phaseTwoResult.setTracer(qResult.getTracer()); int64_t nMaxTimeCost = 0; m_shardResults.clear(); for (size_t i = 0; i < m_requestedShards.size(); ++i) { SearchShardBase* pShard = m_requestedShards[i]; const string& sResult = pShard->getResponse(); if (pShard->getStatus() != SearchReplicaBase::EC_OK) { stringstream ss; ss << "Has error on shard: [" << pShard->getName() << "]: " << parseError(sResult); FX_LOG(ERROR, ss.str().c_str()); setError(ss.str()); SEARCH_LATENCY_END(m_nPhaseTwoCollectLatency); return; } FX_TRACE("Phase2 result: [%s]", sResult.c_str()); XMLResultParser parser; QueryResultPtr& pTmpQRes = m_shardResults[pShard->getShardId()].second; parser.parse(sResult, *(pTmpQRes)); if (pTmpQRes->getTimeCost() > nMaxTimeCost) { nMaxTimeCost = pTmpQRes->getTimeCost(); } // merge trace information QueryTracerPtr& pTracer = pTmpQRes->getTracer(); if (pTracer.isNotNull()) { if (phaseTwoResult.getTracer().isNull()) { phaseTwoResult.setTracer(new QueryTracer("proxy", pTracer->getLevel())); } string str; NumberFormatter::append(str, pShard->getShardId()); phaseTwoResult.getTracer()->addChildTracer(pTracer)->prependPath(str); } } // Merge hit docs phaseTwoResult.setTotalHits(qResult.getTotalHits()); phaseTwoResult.setTimeCost(nMaxTimeCost + qResult.getTimeCost()); QueryResult::Iterator it = qResult.iterator(); while (it.hasNext()) { const ResultDocPtr& pDoc = it.next(); shardid_t shardId = pDoc->getShardId(); FIRTEX_ASSERT2((size_t)shardId <= m_shards.size()); ResultPair& resPair = m_shardResults[shardId]; QueryResultPtr& pQResult2 = resPair.second; if (pQResult2->hasError()) { FX_LOG(ERROR, "Has error on shard: [%d], msg: [%s]", pQResult2->getErrorMsg().c_str()); phaseTwoResult.setError(pQResult2->getErrorMsg()); break; } ResultDocPtr& pDoc2 = (*pQResult2)[resPair.first++]; pDoc2->setScore(pDoc->getScore()); phaseTwoResult.addDoc(pDoc2); } SEARCH_LATENCY_END(m_nPhaseTwoCollectLatency); // Add query trace information QueryTracerPtr& pResTracer = phaseTwoResult.getTracer(); if (pResTracer.isNotNull()) { FX_QUERY_TRACE(DEBUG, pResTracer, "Phase one search latency: [%d] ms", m_nPhaseOneLatency); FX_QUERY_TRACE(DEBUG, pResTracer, "Phase one collection latency: [%d] ms", m_nPhaseOneCollectLatency); FX_QUERY_TRACE(DEBUG, pResTracer, "Phase two search latency: [%d] ms", m_nPhaseTwoLatency); FX_QUERY_TRACE(DEBUG, pResTracer, "Phase two collection latency: [%d] ms", m_nPhaseTwoCollectLatency); } FX_DEBUG("Begin format result"); stringstream ss; XMLResultFormatter formatter; formatter.format(phaseTwoResult, ss); m_sResult = ss.str(); FX_DEBUG("End format result"); }
void HTTPSearchService::handleQuery(const Statement& state, EvHttpRequestContext* pCtx) const { IndexReaderPtr pIndexReader = m_searchRes.getIndexReader(); FIRTEX_ASSERT2(pIndexReader.isNotNull()); try { TimeProbe probe; probe.start(); QueryParser parser(pIndexReader->getAnalyzerMapper(), m_searchRes.getDefaultField()); IndexSearcher searcher(pIndexReader); QueryHitsPtr pHits = searcher.search(state, parser); QueryResult result; if (pHits.isNotNull()) { FieldSelectClausePtr pFieldClause = state.getFieldSelectClause(); QueryClausePtr pQueryClause = state.getQueryClause(); if (pFieldClause.isNotNull() && pQueryClause.isNotNull()) { QueryPtr pQuery = parser.parse(pQueryClause->getQueryString()); FIRTEX_ASSERT2(pQuery.isNotNull()); FieldSelector selector(pIndexReader->getDocSchema()); for (size_t i = 0; i < pFieldClause->getFieldCount(); ++i) { const FieldSelectClause::SnippetParam& param = pFieldClause->getField(i); FieldFilterPtr pFieldFilter; if (param.snippet) { SnippetGenerator* pSnippetGen = new SnippetGenerator(); pFieldFilter.reset(pSnippetGen); if (!pSnippetGen->init(pQuery, parser.getAnalyzerMapper(), param.field, param.preTag, param.postTag, param.separator)) { FX_LOG(ERROR, "Init snippet generator for field: [%s] FAILED", param.field.c_str()); sendErrorMessage("Init snippet generator for field: " + param.field + " FAILED", pCtx); return; } } if (!selector.addField(param.field, pFieldFilter)) { FX_LOG(ERROR, "Invalid field: [%s]", param.field.c_str()); } } result.init(selector, pIndexReader, *pHits); } else { result.init(pIndexReader, *pHits); } } probe.stop(); result.setTimeCost(probe.elapsed() / 1000); FX_QUERY_TRACE(INFO, result.getTracer(), "search phase time [%d]", (int32_t)result.getTimeCost()); stringstream ss; XMLResultFormatter formatter; formatter.format(result, ss); sendResponse(ss.str(), pCtx); } catch(const FirteXException& e) { FX_LOG(ERROR, "Handle request FAILED: [%s], reason: [%s]", pCtx->getQuery().c_str(), e.what().c_str()); sendErrorMessage("Handle request failed", pCtx); } }
void XMLResultFormatter::format(const QueryResult& result, std::stringstream& ss) { m_xmlDoc.clear(); m_xmlDoc.addDeclarationNode(result.getEncoding()); XMLNodeWrapperPtr pRootNode = m_xmlDoc.appendNode( XMLDocumentWrapper::NODE_ELEMENT, "result"); if (result.hasError()) { formatError(pRootNode, result.getErrorMsg()); } else { XMLNodeWrapperPtr resultNode = pRootNode->appendNode( XMLDocumentWrapper::NODE_ELEMENT, "hits"); string str; NumberFormatter::append(str, (int32_t)result.size()); resultNode->appendAttribute("number_hits", str); str.clear(); NumberFormatter::append(str, result.getTotalHits()); resultNode->appendAttribute("total_hits", str); str.clear(); NumberFormatter::append(str, result.getTimeCost()); resultNode->appendAttribute("cost", str); QueryResult::Iterator it = result.iterator(); while (it.hasNext()) { XMLNodeWrapperPtr pHitNode = resultNode->appendNode( XMLDocumentWrapper::NODE_ELEMENT, "hit"); const ResultDocPtr& pResDoc = it.next(); if (result.hasShardId()) { str.clear(); NumberFormatter::append(str, pResDoc->getShardId()); pHitNode->appendNode(XMLDocumentWrapper::NODE_ELEMENT, "shardid", str); } if (result.hasDocId()) { str.clear(); NumberFormatter::append(str, pResDoc->getDocId()); pHitNode->appendNode(XMLDocumentWrapper::NODE_ELEMENT, "docid", str); } if (result.hasScore()) { str.clear(); NumberFormatter::append(str, pResDoc->getScore(), 2); pHitNode->appendNode(XMLDocumentWrapper::NODE_ELEMENT, "score", str); } if (result.hasFields()) { XMLNodeWrapperPtr pFieldsNode = pHitNode->appendNode( XMLDocumentWrapper::NODE_ELEMENT, "fields"); ResultDoc::Iterator fieldIt = pResDoc->iterator(); while (fieldIt.hasNext()) { const ResultDoc::Field& field = fieldIt.next(); XMLNodeWrapperPtr pCDataNode = pFieldsNode->appendNode( XMLDocumentWrapper::NODE_ELEMENT, field.first); pCDataNode->appendNode(XMLDocumentWrapper::NODE_CDATA, "", field.second); } } } // end while const QueryTracerPtr& pTracer = result.getTracer(); if (pTracer) { formatTracer(pRootNode, pTracer); } } m_xmlDoc.print(ss); }