/// <summary> /// 构建分词 /// </summary> /// <param name="query">带分词的语句</param> /// <param name="index">引用的索引库</param> /// <returns>分词集合</returns> public IList<SphinxKeyWord> BuildKeywords(string query, string index) { Contract.Requires(false == string.IsNullOrWhiteSpace(query), "query can not be null or emtpy"); Contract.Requires(false == string.IsNullOrWhiteSpace(index), "index can not be null or empty"); var req = new SphReq(); req.Write(query); req.Write(index); req.Write(1); var tmp = new SphReq(); tmp.Write(1); tmp.Write((short)SearchCommand.SEARCHD_COMMAND_KEYWORDS); tmp.Write((short)Command.VER_COMMAND_KEYWORDS); tmp.Write((int)req.Length); req.Mosaic(tmp.CutOffHead(), SphReq.BlockMosaicLocation.Top); var conn = this.GetConnection(); conn.Send(req.GetBuffer()); var rece = new byte[5 * req.Length]; var receLength = conn.Receive(rece); var rep = new SphRep(rece, receLength); var rLen = this.CheckResponse(rep); var nwords = rep.ReadInt(); var res = new List<SphinxKeyWord>(); for (int i = 0; i < nwords; i++) res.Add(new SphinxKeyWord(rep.ReadStringNode(), rep.ReadStringNode(), rep.ReadInt(), rep.ReadInt())); return res; }
/// <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; }
/// <summary> /// 构建摘录 /// </summary> /// <param name="docs">待构建的字符串集合</param> /// <param name="index">引用的索引库</param> /// <param name="words">关键字字串</param> /// <param name="options">构建选型</param> /// <returns>构建完成的摘录集合</returns> public IList<string> BuildExcerpts(IList<string> docs, string index, string words, SphinxBuildExceptsOptions options) { Contract.Requires(false == string.IsNullOrWhiteSpace(index), "index can not be null"); Contract.Requires(false == string.IsNullOrWhiteSpace(words), "words can not be null"); var flag = 1; if (options.ExactPhrase) flag |= 2; if (options.SinglePassage) flag |= 4; if (options.UseBoundaries) flag |= 8; if (options.WeightOrder) flag |= 16; var req = new SphReq(); req.Write(0); req.Write(flag); req.Write(index); req.Write(words); req.Write(options.BeforeMatch); req.Write(options.AfterMatch); req.Write(options.ChunkSeparator); req.Write(options.Limit); req.Write(options.Around); req.Write(docs.Count()); foreach (var doc in docs) req.Write(doc); var tmp = new SphReq(); tmp.Write(1); tmp.Write((short)SearchCommand.SEARCHD_COMMAND_EXCERPT); tmp.Write((short)Command.VER_COMMAND_EXCERPT); var reqLength = (int)req.Length; tmp.Write(reqLength); req.Mosaic(tmp.CutOffHead(), SphReq.BlockMosaicLocation.Top); var conn = this.GetConnection(); conn.Send(req.GetBuffer()); var rece = new byte[(int)(1.5 * reqLength)]; var receLength = conn.Receive(rece); conn.Close(); var rep = new SphRep(rece, receLength); var repLength = this.CheckResponse(rep); var res = new List<string>(); for (int i = 0; i < docs.Count(); i++) res.Add(rep.ReadStringNode()); return res; }