// 一次检索多个检索词 // "册条码"; // "参考ID"; // parameters: // bMixRefID 是否在条码号中间杂了 @refID: 前缀的元素? // return: // -1 出错 // 0 一个也没有命中 // >0 命中的总个数。注意,这不一定是results中返回的元素个数。results中返回的个数还要受到nMax的限制,不一定等于全部命中个数 public int GetItemRec( // RmsChannelCollection channels, RmsChannel channel, string strDbType, string strWordList, string strFrom, int nMax, string strStyle, out bool bMixRefID, out List<Record> results, out string strError) { strError = ""; bMixRefID = false; results = new List<Record>(); LibraryApplication app = this; List<string> dbnames = null; int nRet = app.GetDbNames( strDbType, out dbnames, out strError); if (nRet == -1) return -1; string strRefIDList = ""; if (strFrom == "册条码" || strFrom == "册条码号") { string strNormalList = ""; // 将一个检索词列表中的,带有 @refID 的部分检索词拆为另外一个 list SplitWordList(strWordList, out strNormalList, out strRefIDList); strWordList = strNormalList; } // 构造检索式 string strQueryXml = ""; int nDbCount = 0; for (int i = 0; i < dbnames.Count; i++) { string strDbName = dbnames[i]; if (String.IsNullOrEmpty(strDbName) == true) continue; if (string.IsNullOrEmpty(strWordList) == false) { string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + strFrom) // 2007/9/14 + "'><item><word>" + StringUtil.GetXmlStringSimple(strWordList) + "</word><match>exact</match><relation>list</relation><dataType>string</dataType><maxCount>" + nMax.ToString() + "</maxCount></item><lang>zh</lang></target>"; if (nDbCount > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; nDbCount++; } if (string.IsNullOrEmpty(strRefIDList) == false) { bMixRefID = true; string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + "参考ID") + "'><item><word>" + StringUtil.GetXmlStringSimple(strRefIDList) + "</word><match>exact</match><relation>list</relation><dataType>string</dataType><maxCount>" + nMax.ToString() + "</maxCount></item><lang>zh</lang></target>"; if (nDbCount > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; nDbCount++; } } if (nDbCount > 0) { strQueryXml = "<group>" + strQueryXml + "</group>"; } #if NO RmsChannel channel = channels.GetChannel(app.WsUrl); if (channel == null) { strError = "get channel error"; return -1; } #endif if (channel == null) throw new ArgumentException("channel 参数值不能为空", "channel"); Record[] records = null; long lRet = channel.DoSearchEx(strQueryXml, "default", strStyle, // strOuputStyle nMax, "zh", strStyle + ",id", // "id,xml,timestamp", out records, out strError); if (lRet == -1) goto ERROR1; // not found if (lRet == 0) { strError = "所有检索词一个也没有命中"; return 0; } long lHitCount = lRet; if (nMax == -1) nMax = (int)lHitCount; else { if (nMax > lHitCount) nMax = (int)lHitCount; } if (records == null || records.Length == 0) { strError = "records error"; return -1; } results.AddRange(records); if (results.Count == lHitCount) return (int)lHitCount; // 如果第一次没有取完,需要继续取得 if (nMax > records.Length) { long lStart = records.Length; long lCount = nMax - lStart; for (; ; ) { lRet = channel.DoGetSearchResult( "default", lStart, lCount, strStyle + ",id", // "id,xml,timestamp", "zh", null, out records, out strError); if (lRet == -1) goto ERROR1; Debug.Assert(records != null, ""); if (records.Length == 0) { strError = "DoGetSearchResult records error"; goto ERROR1; } results.AddRange(records); lStart += records.Length; if (lStart >= lHitCount || lStart >= nMax) break; lCount -= records.Length; } } return (int)lHitCount; ERROR1: return -1; }
// 检索一个册记录或者评注\订购\期记录 // 本函数可获得超过1条以上的路径 // parameters: // strBarcode 册条码号。也可以为 "@refID:值" 形态 // strStyle 如果包含 withresmetadata ,表示要在XML记录中返回<dprms:file>元素内的 __xxx 属性 2012/11/19 // 如果包含 xml, 则表示返回 XML 记录体 // 如果包含 timestamp, 则表示返回时间戳 // return: // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条 public int GetOneItemRec( // RmsChannelCollection channels, RmsChannel channel, string strDbType, string strBarcode, string strFrom, string strStyle, out string strXml, int nMax, out List<string> aPath, out byte[] timestamp, out string strError) { aPath = null; strXml = ""; strError = ""; timestamp = null; LibraryApplication app = this; List<string> dbnames = null; int nRet = app.GetDbNames( strDbType, out dbnames, out strError); if (nRet == -1) return -1; #if NO // 构造检索式 string strQueryXml = ""; int nDbCount = 0; for (int i = 0; i < dbnames.Count; i++) { string strDbName = dbnames[i]; if (String.IsNullOrEmpty(strDbName) == true) continue; string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + strFrom) // 2007/9/14 + "'><item><word>" + StringUtil.GetXmlStringSimple(strBarcode) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>" + nMax.ToString() + "</maxCount></item><lang>zh</lang></target>"; if (nDbCount > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; nDbCount++; } if (nDbCount > 0) { strQueryXml = "<group>" + strQueryXml + "</group>"; } #endif string strHint = ""; if (StringUtil.IsInList("first", strStyle) == true) { strHint = " hint='first' "; StringUtil.SetInList(ref strStyle, "first", false); // 去掉 first 子串。因为 strStyle 这个用法只有在本函数有意义 } string strQueryXml = ""; { // 构造检索式 // 新方法只用一个 item 元素,把各个库的 dbname 和 from 都拍紧到同一个 targetlist 中 StringBuilder targetList = new StringBuilder(); for (int i = 0; i < dbnames.Count; i++) { string strDbName = dbnames[i]; if (String.IsNullOrEmpty(strDbName) == true) continue; if (targetList.Length > 0) targetList.Append(";"); targetList.Append(strDbName + ":" + strFrom); } if (targetList.Length == 0) { strError = "没有任何可检索的目标数据库"; return -1; } strQueryXml = "<target list='" + StringUtil.GetXmlStringSimple(targetList.ToString()) + "' " + strHint + "><item><word>" + StringUtil.GetXmlStringSimple(strBarcode) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>" + nMax.ToString() + "</maxCount></item><lang>zh</lang></target>"; } if (channel == null) throw new ArgumentException("channel 参数不应为空", "channel"); Record[] records = null; long lRet = channel.DoSearchEx(strQueryXml, "default", "", // strOuputStyle 1, "zh", strStyle + ",id", // "id,xml,timestamp", out records, out strError); if (lRet == -1) goto ERROR1; // not found if (lRet == 0) { strError = strFrom + " '" + strBarcode + "' 没有找到"; return 0; } long lHitCount = lRet; if (records == null || records.Length == 0) { strError = "records error"; return -1; } #if DEBUG if (StringUtil.IsInList("xml", strStyle) == true || StringUtil.IsInList("timestamp", strStyle) == true) { Debug.Assert(records[0].RecordBody != null, ""); } #endif aPath = new List<string>(); aPath.Add(records[0].Path); if (records[0].RecordBody != null) { strXml = records[0].RecordBody.Xml; timestamp = records[0].RecordBody.Timestamp; } // 如果命中结果多余一条,则继续获得第一条以后的各条的path if (lHitCount > 1) // TODO: && nMax > 1 { // List<string> aPath = null; lRet = channel.DoGetSearchResult( "default", 0, Math.Min(nMax, lHitCount), "zh", null, out aPath, out strError); if (lRet == -1) goto ERROR1; Debug.Assert(aPath != null, ""); if (aPath.Count == 0) { strError = "DoGetSearchResult aPath error"; goto ERROR1; } } return (int)lHitCount; ERROR1: return -1; }
// 2012/1/6 改造为PiggyBack检索 // TODO: 判断strWord是否为空 // 通过特定检索途径获得读者记录 // parameters: // strReaderDbNames 读者库名列表。如果为空,表示采用当前配置的全部读者库 // nMax 希望在 recpaths 中最多返回多少个记录路径 // strLibraryCodeList 馆代码列表,仅返回属于这个列表管辖的读者库的记录和路径。如果为空,表示不过滤 // recpaths [out]返回命中的记录路径。如果发生重复,这里会返回多于一个路径 // return: // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条 public int GetReaderRecXmlByFrom( // RmsChannelCollection channels, RmsChannel channel, string strReaderDbNames, string strWord, string strFrom, int nMax, string strLibraryCodeList, out List<string> recpaths, out string strXml, // out string strOutputPath, out byte[] timestamp, out string strError) { // strOutputPath = ""; timestamp = null; strXml = ""; strError = ""; int nRet = 0; recpaths = new List<string>(); LibraryApplication app = this; #if NO List<string> dbnames = new List<string>(); if (string.IsNullOrEmpty(strReaderDbNames) == true) { for (int i = 0; i < app.ReaderDbs.Count; i++) { string strDbName = app.ReaderDbs[i].DbName; if (string.IsNullOrEmpty(strDbName) == true) { Debug.Assert(false, ""); continue; } if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false && IsCurrentChangeableReaderPath(strDbName + "/?", strLibraryCodeList) == false) continue; dbnames.Add(strDbName); } if (dbnames.Count == 0) { strError = "当前尚没有配置读者库"; return -1; } } else { dbnames = StringUtil.SplitList(strReaderDbNames); StringUtil.RemoveBlank(ref dbnames); if (dbnames.Count == 0) { strError = "参数strReaderDbNames值 '" + strReaderDbNames + "' 中没有包含有效的读者库名"; return -1; } } #endif List<string> dbnames = new List<string>(); // 获得读者库名列表 // parameters: // strReaderDbNames 库名列表字符串。如果为空,则表示全部读者库 // return: // -1 出错 // >=0 dbnames 中包含的读者库名数量 nRet = GetDbNameList(strReaderDbNames, strLibraryCodeList, out dbnames, out strError); if (nRet == -1) return -1; if (dbnames.Count == 0) { if (app.ReaderDbs.Count == 0) strError = "当前尚没有配置读者库"; else strError = "当前没有可以操作的读者库"; return -1; } // 构造检索式 string strQueryXml = ""; for (int i = 0; i < dbnames.Count; i++) { string strDbName = dbnames[i]; Debug.Assert(String.IsNullOrEmpty(strDbName) == false, ""); string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + strFrom) // 2007/9/14 + "'><item><word>" + StringUtil.GetXmlStringSimple(strWord) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>1000</maxCount></item><lang>zh</lang></target>"; if (i > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; } if (dbnames.Count > 0) { strQueryXml = "<group>" + strQueryXml + "</group>"; } #if NO RmsChannel channel = channels.GetChannel(app.WsUrl); if (channel == null) { strError = "get channel error"; return -1; } #endif Record[] records = null; long lRet = channel.DoSearchEx(strQueryXml, "default", "", // strOuputStyle 1, "zh", "id,xml,timestamp", out records, out strError); if (lRet == -1) goto ERROR1; // not found if (lRet == 0) { strError = "读者" + strFrom + " '" + strWord + "' 没有找到"; return 0; } long lHitCount = lRet; if (records == null || records.Length == 0) { strError = "records error"; return -1; } Debug.Assert(records[0].RecordBody != null, ""); // strOutputPath = records[0].Path; if (nMax >= 1) recpaths.Add(records[0].Path); strXml = records[0].RecordBody.Xml; timestamp = records[0].RecordBody.Timestamp; // 如果命中结果多于一条,则继续获得第一条以后的各条的path if (lHitCount > 1 && nMax > 1) { // List<string> temp = null; lRet = channel.DoGetSearchResult( "default", 0, Math.Min(nMax, lHitCount), "zh", null, out recpaths, out strError); if (lRet == -1) goto ERROR1; Debug.Assert(recpaths != null, ""); if (recpaths.Count == 0) { strError = "DoGetSearchResult aPath error"; goto ERROR1; } } return (int)lHitCount; ERROR1: return -1; }
// 2014/9/19 strBarcode 可以包含 @refID: 前缀了 // 2012/1/5 改造为PiggyBack检索 // TODO: 判断strBarcode是否为空 // 获得册记录 // 本函数为了执行效率方面的原因, 不去获得超过1条以上的路径。所返回的重复条数最大为1000 // return: // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条(即便在这种情况下, strOutputPath也返回了第一条的路径) public int GetItemRecXml( RmsChannel channel, string strBarcodeParam, string strStyle, out string strXml, out string strOutputPath, out byte[] timestamp, out string strError) { strOutputPath = ""; strXml = ""; strError = ""; timestamp = null; LibraryApplication app = this; string strBarcode = strBarcodeParam; string strHead = "@refID:"; string strFrom = "册条码"; if (StringUtil.HasHead(strBarcode, strHead, true) == true) { strFrom = "参考ID"; strBarcode = strBarcode.Substring(strHead.Length).Trim(); if (string.IsNullOrEmpty(strBarcode) == true) { strError = "字符串 '" + strBarcodeParam + "' 中 参考ID 部分不应为空"; return -1; } } // 构造检索式 string strQueryXml = ""; int nDbCount = 0; for (int i = 0; i < app.ItemDbs.Count; i++) { string strDbName = app.ItemDbs[i].DbName; // 2008/10/16 if (String.IsNullOrEmpty(strDbName) == true) continue; // 2007/4/5 改造 加上了 GetXmlStringSimple() string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + strFrom) + "'><item><word>" + StringUtil.GetXmlStringSimple(strBarcode) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>1000</maxCount></item><lang>zh</lang></target>"; // 1000 2011/9/5 if (nDbCount > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; nDbCount++; } if (nDbCount > 0) { strQueryXml = "<group>" + strQueryXml + "</group>"; } string strBrowseStyle = "id,xml,timestamp"; if (strStyle == "parent") strBrowseStyle = "id,cols,format:@coldef://parent"; Record[] records = null; long lRet = channel.DoSearchEx(strQueryXml, "default", "", // strOuputStyle 1, "zh", strBrowseStyle, // "id,xml,timestamp", out records, out strError); if (lRet == -1) goto ERROR1; // not found if (lRet == 0) { strError = "册条码号 '" + strBarcode + "' 没有找到"; return 0; } long lHitCount = lRet; if (records == null || records.Length == 0) { strError = "records error"; return -1; } if (strStyle == "parent") { strOutputPath = records[0].Path; strXml = records[0].Cols[0]; } else { Debug.Assert(records[0].RecordBody != null, ""); strOutputPath = records[0].Path; strXml = records[0].RecordBody.Xml; timestamp = records[0].RecordBody.Timestamp; } return (int)lHitCount; ERROR1: return -1; }
// 2012/1/5 改造为PiggyBack检索 // 2013/5/23 改造为可以返回所有命中的 记录路径 // TODO: 判断strBarcode是否为空 // 通过读者证条码号获得读者记录 // return: // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条 public int GetReaderRecXml( // RmsChannelCollection channels, RmsChannel channel, string strBarcodeParam, int nMax, string strLibraryCodeList, out List<string> recpaths, out string strXml, // out string strOutputPath, out byte[] timestamp, out string strError) { // strOutputPath = ""; timestamp = null; strXml = ""; strError = ""; int nRet = 0; recpaths = new List<string>(); LibraryApplication app = this; string strBarcode = strBarcodeParam; string strHead = "@refID:"; string strFrom = "证条码"; if (StringUtil.HasHead(strBarcode, strHead, true) == true) { strFrom = "参考ID"; strBarcode = strBarcode.Substring(strHead.Length).Trim(); if (string.IsNullOrEmpty(strBarcode) == true) { strError = "字符串 '" + strBarcodeParam + "' 中 参考ID 部分不应为空"; return -1; } } List<string> dbnames = new List<string>(); // 获得读者库名列表 // parameters: // strReaderDbNames 库名列表字符串。如果为空,则表示全部读者库 // return: // -1 出错 // >=0 dbnames 中包含的读者库名数量 nRet = GetDbNameList("", strLibraryCodeList, out dbnames, out strError); if (nRet == -1) return -1; // 构造检索式 string strQueryXml = ""; // int nInCount = 0; // 参与流通的读者库个数 foreach (string strDbName in dbnames) { // string strDbName = app.ReaderDbs[i].DbName; if (string.IsNullOrEmpty(strDbName) == true) { Debug.Assert(false, ""); continue; } // 2007/4/5 改造 加上了 GetXmlStringSimple() string strOneDbQuery = "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + strFrom) // "证条码" // TODO: 将来统一修改为“证条码号” // 2007/9/14 + "'><item><word>" + StringUtil.GetXmlStringSimple(strBarcode) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>1000</maxCount></item><lang>zh</lang></target>"; if (String.IsNullOrEmpty(strQueryXml) == false) // i > 0 { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += strOneDbQuery; // nInCount++; } if (string.IsNullOrEmpty(strQueryXml) == true /*nInCount == 0*/) { if (app.ReaderDbs.Count == 0) strError = "当前尚没有配置读者库"; else strError = "当前没有可以操作的读者库"; return -1; } if (dbnames.Count > 0/*nInCount > 0*/) { strQueryXml = "<group>" + strQueryXml + "</group>"; } #if NO RmsChannel channel = channels.GetChannel(app.WsUrl); if (channel == null) { strError = "get channel error"; return -1; } #endif Record[] records = null; long lRet = channel.DoSearchEx(strQueryXml, "default", "", // strOuputStyle 1, "zh", "id,xml,timestamp", out records, out strError); if (lRet == -1) goto ERROR1; // not found if (lRet == 0) { strError = "读者证条码号 '" + strBarcode + "' 没有找到"; return 0; } long lHitCount = lRet; if (records == null || records.Length == 0) { strError = "records error"; return -1; } Debug.Assert(records[0].RecordBody != null, ""); // strOutputPath = records[0].Path; if (nMax >= 1) recpaths.Add(records[0].Path); strXml = records[0].RecordBody.Xml; timestamp = records[0].RecordBody.Timestamp; // 如果命中结果多余一条,则继续获得第一条以后的各条的path if (lHitCount > 1 && nMax > 1) { // List<string> temp = null; lRet = channel.DoGetSearchResult( "default", 0, Math.Min(nMax, lHitCount), "zh", null, out recpaths, out strError); if (lRet == -1) goto ERROR1; Debug.Assert(recpaths != null, ""); if (recpaths.Count == 0) { strError = "DoGetSearchResult recpaths error"; goto ERROR1; } } return (int)lHitCount; ERROR1: return -1; }