public void GetRenderedConcordance(ref string query, int ofs, out string html, string lang, bool isMobile, HttpContext ctxt) { StringBuilder sb = new StringBuilder(); html = ""; int limit = pageSize; query = query.Trim(); string queryToLog = query; if (query.Length == 0) { return; } bool isZhoSearch = hasHanzi(query); if (!isZhoSearch) { query = pruneSurf(query, true, null); } // Lookup timer Stopwatch swatch = new Stopwatch(); swatch.Restart(); // Lookup SphinxResult sres = sphinx.Query(query, isZhoSearch, ofs, limit); // If first page, show result count on top if (ofs == 0 && sres.TotalCount > 0) { sb.Append("<p class='corpresultcount'><span>"); sb.Append(HtmlEncoder.Default.Encode(getResultCountStr(lang, sres.TotalCount))); sb.AppendLine("</span></p>"); } using (BinReader br = new BinReader(sphinx.CorpusBinFileName)) { List <float> trgHilites = new List <float>(); List <float> srcHilites = new List <float>(); HashSet <int> usedPoss = new HashSet <int>(); int resultCount = 0; // Render surface search results foreach (int pos in sres.SurfSegPositions) { ++resultCount; usedPoss.Add(pos); br.Position = pos; CorpusSegment cseg = new CorpusSegment(br); if (isZhoSearch) { buildHilitesZhoToHu(query, cseg, trgHilites, srcHilites); } else { buildHilitesHuToZho(query, null, cseg, trgHilites, srcHilites); } sb.Append("<div class='corprow'><div class='corpseg zho'>"); sb.Append(renderSegment(cseg.ZhSurf, srcHilites, isZhoSearch)); sb.Append("</div><div class='corpseg trg'>"); sb.Append(renderSegment(cseg.TrgSurf, trgHilites, isZhoSearch)); sb.AppendLine("</div></div>"); } // Render stem search results to fill up to limit for (int i = 0; i < sres.StemmedSegs.Count && resultCount < limit; ++i) { int pos = sres.StemmedSegs[i].Key; if (usedPoss.Contains(pos)) { continue; } ++resultCount; br.Position = pos; CorpusSegment cseg = new CorpusSegment(br); buildHilitesHuToZho(sres.StemmedQuery, sres.StemmedSegs[i].Value, cseg, trgHilites, srcHilites); sb.Append("<div class='corprow'><div class='corpseg zho'>"); sb.Append(renderSegment(cseg.ZhSurf, srcHilites, isZhoSearch)); sb.Append("</div><div class='corpseg trg'>"); sb.Append(renderSegment(cseg.TrgSurf, trgHilites, isZhoSearch)); sb.AppendLine("</div></div>"); } } // "Load more" button if (sres.TotalCount > ofs + limit) { string strMore = TextProvider.Instance.GetString(lang, "search.corpusLoadMore"); sb.Append("<div class='corpmore'>"); sb.Append("<div class='corpmorebtn' data-offset='" + (ofs + limit).ToString() + "' "); sb.Append("data-query='" + HtmlEncoder.Default.Encode(query) + "'>"); sb.Append(HtmlEncoder.Default.Encode(strMore)); sb.Append("<i class='fa fa-circle-o-notch fa-fw'></i>"); sb.AppendLine("</div></div>"); } // The response! html = sb.ToString(); // Query log int msecFull = (int)swatch.ElapsedMilliseconds; int msecPerlOuter = (int)(1000.0F * sres.PerlOuterElapsed); string country; string xfwd = ctxt.Request.Headers["X-Real-IP"]; if (xfwd != null) { country = cres.GetContryCode(IPAddress.Parse(xfwd)); } else { country = cres.GetContryCode(ctxt.Connection.RemoteIpAddress); } qlog.LogCorpus(country, isMobile, lang, sres.TotalCount, msecPerlOuter, msecFull, isZhoSearch, ofs > 0, query); }
/// <summary> /// 执行查询 /// </summary> /// <returns></returns> public IList<SphinxResult> RunQueries() { var reqsCount = this._reqs.Count(); var reqsLength = this._reqs.Sum(r => r.Length); var req = new SphReq(); req.Write(1); req.Write((short)SearchCommand.SEARCHD_COMMAND_SEARCH); req.Write((short)Command.VER_COMMAND_SEARCH); req.Write((int)(4 + reqsLength)); req.Write(reqsCount); foreach (var r in this._reqs) req.Mosaic(r.CutOffHead()); var conn = this.GetConnection(); conn.Send(req.GetBuffer()); var receive = new byte[1024 * 512]; var receLen = conn.Receive(receive); conn.Dispose(); var rep = new SphRep(receive, receLen); var len = this.CheckResponse(rep); var sphinxResultList = new List<SphinxResult>(); for (int rc = 0; rc < reqsCount; rc++) { var sphinxResult = new SphinxResult() { AttrName = new List<string>(), AttrTypes = new List<int>(), Fields = new List<string>(), Matches = new List<SphinxMatch>(), Words = new List<SphinxWordInfo>(), Status = rep.ReadInt() }; if (sphinxResult.Status != (int)SearchStatus.SEARCHD_OK) { if (sphinxResult.Status == (int)SearchStatus.SEARCHD_WARNING) { sphinxResult.WarnStr = Encoding.UTF8.GetString(rep.Read(len - 4)); } else { sphinxResult.ErrStr = Encoding.UTF8.GetString(rep.Read(len - 4)); return null; } } var fieldsNum = rep.ReadInt(); for (int i = 0; i < fieldsNum; i++) sphinxResult.Fields.Add(rep.ReadStringNode()); var attrNum = rep.ReadInt(); for (int i = 0; i < attrNum; i++) { sphinxResult.AttrName.Add(rep.ReadStringNode()); sphinxResult.AttrTypes.Add(rep.ReadInt()); } var matchNum = rep.ReadInt(); var id64 = rep.ReadInt(); long doc; for (int i = 0; i < matchNum; i++) { doc = 0 == id64 ? rep.ReadInt() : rep.ReadLong(); var docInfo = new SphinxMatch() { DocID = doc, Weight = rep.ReadInt(), AttrValues = new List<object>() }; foreach (var type in sphinxResult.AttrTypes) { switch ((AttributeType)System.Enum.Parse(typeof(AttributeType), type.ToString())) { case AttributeType.SPH_ATTR_BIGINT: docInfo.AttrValues.Add(rep.ReadLong()); rep.Read(8); break; case AttributeType.SPH_ATTR_FLOAT: docInfo.AttrValues.Add(rep.ReadSingle()); rep.Read(8); break; case AttributeType.SPH_ATTR_MULTI: var itemsNum = rep.ReadLong(); var vars = new List<long>(); for (int j = 0; j < itemsNum; j++) vars.Add(rep.ReadLong()); docInfo.AttrValues.Add(vars); break; default: rep.Read(8); docInfo.AttrValues.Add(rep.ReadLong()); break; } } sphinxResult.Matches.Add(docInfo); } sphinxResult.Total = rep.ReadInt(); sphinxResult.TotalFound = rep.ReadInt(); sphinxResult.Time = rep.ReadInt(); var wordNum = rep.ReadInt(); for (int i = 0; i < wordNum; i++) sphinxResult.Words.Add(new SphinxWordInfo() { Word = rep.ReadStringNode(), Docs = rep.ReadInt(), Hits = rep.ReadInt() }); sphinxResultList.Add(sphinxResult); } return sphinxResultList; }
public IActionResult Go([FromQuery] string query) { int limit = 100; SearchResult res = new SearchResult(); query = query.Trim(); res.ActualQuery = query; if (query.Length == 0) { return(new ObjectResult(res)); } bool isZhoSearch = hasHanzi(query); if (!isZhoSearch) { query = pruneSurf(query, true, null); } res.ActualQuery = query; SphinxResult sres = Sphinx.Query(query, isZhoSearch, limit); if (sres == null) { return(StatusCode(500)); } using (BinReader br = new BinReader("zhhu-data.bin")) { List <float> trgHilites = new List <float>(); List <float> srcHilites = new List <float>(); HashSet <int> usedPoss = new HashSet <int>(); int resultCount = 0; // Render surface search results foreach (int pos in sres.SurfSegPositions) { ++resultCount; usedPoss.Add(pos); br.Position = pos; CorpusSegment cseg = new CorpusSegment(br); if (isZhoSearch) { buildHilitesZhoToHu(query, cseg, trgHilites, srcHilites); } else { buildHilitesHuToZho(query, null, cseg, trgHilites, srcHilites); } res.SrcSegs.Add(renderSegment(cseg.ZhSurf, srcHilites, isZhoSearch)); res.TrgSegs.Add(renderSegment(cseg.TrgSurf, trgHilites, isZhoSearch)); } // Render stem search results to fill up to limit for (int i = 0; i < sres.StemmedSegs.Count && resultCount < limit; ++i) { int pos = sres.StemmedSegs[i].Key; if (usedPoss.Contains(pos)) { continue; } ++resultCount; br.Position = pos; CorpusSegment cseg = new CorpusSegment(br); buildHilitesHuToZho(sres.StemmedQuery, sres.StemmedSegs[i].Value, cseg, trgHilites, srcHilites); res.SrcSegs.Add(renderSegment(cseg.ZhSurf, srcHilites, isZhoSearch)); res.TrgSegs.Add(renderSegment(cseg.TrgSurf, trgHilites, isZhoSearch)); } } return(new ObjectResult(res)); }