ifs.old=$ifs

    技术2022-07-21  89

    总览

    用于DB2 for i的IBM OmniFind Text Search Server产品是一项免费产品,它使IBM i开发人员可以索引和搜索存储在DB2中的文本文档(包括Microsoft Word,PDF,XML等富文本文档)。柱。 例如,如果我有一个包含短故事的CLOB列,并且我想检索该列中包含与“大灰狼”有关的数据的行,那么即使使用SQL Server内置函数也可以查找这些行。该行的栏中包含的实际文字是“大灰狼”。 此外,我可以对匹配的行进行排序,以便最相关的文档排在结果集中。

    在DB2列中搜索文本数据确实是一个很棒的功能,但是并不是系统上所有有趣的文本数据都存储在DB2中。 例如,您可能需要搜索“输出队列”中假脱机文件中存储的一组报告。 或者假设您要搜索包含PDF数据的IFS流文件。 幸运的是,从IBM i 7.1开始,存在一个解决方案,该解决方案使我们能够索引和搜索与这些IBM i对象关联的文本数据。

    软件需求

    为了使用本文中描述的功能,必须订购和安装OmniFind文本搜索服务器V1R2产品(5733-OMF),并应用IBM i 7.1 PTF SI45696。 通常,最佳实践是在加载PTF的同时,在系统上应用适用于IBM i 7.1的最新IBM Database Group PTF。 此外,OmniFind产品还需要在系统上安装其他一些产品。 这些必需的软件产品记录在OmniFind参考手册中 。

    支持的对象类型和文本属性

    IBM i对象通常具有多个文本属性。 例如,输出队列具有与之关联的文本描述–并且还包含其中包含文本的假脱机文件。 为了使IBM扩展对不同对象和文本信息的支持,我们选择通过对象和包含文本的对象属性来标识文本。 例如,输出队列NICK / QUEUE1中特定假脱机文件的数据,或流文件/home/nick/file1.txt中的数据。

    在输出队列中假脱机文件

    具有SNA字符流(SCS)数据的假脱机文件包含打印机输出,该输出格式化为EBCDIC文本数据。 以SCS格式创建的假脱机文件通常用于将报告和作业日志存储在输出队列中,以便以后可以由应用程序处理。

    尽管假脱机文件存在于输出队列中,但通常使用其他条件来选择它们。 例如,工作假脱机文件命令( WRKSPLF )使用文件名,作业,假脱机文件编号,创建系统和创建时间戳来标识假脱机文件。

    OmniFind提供了几种基于其他系统API和CL命令使用的选择标准来识别要索引的SCS假脱机文件的方法。

    使用非SCS格式的假脱机文件不那么常见,并且更难从中提取文本,OmniFind不支持它们。

    有关假脱机文件的更多信息,请参见信息中心 。

    IFS流文件

    集成文件系统(IFS)提供了一组分层文件系统,类似于UNIX®环境中使用的文件系统。 每个文件系统都有其自己的独特属性,例如区分大小写和允许的对象类型。

    OmniFind支持使用IFS路径标识流文件对象中的文本数据。 流文件对象(* STMF)是字节的随机访问序列,系统没有施加其他结构。 流文件的更简单定义是PC文件或UNIX®文件。

    可以索引和搜索包含纯文本或富文本的Steam文件。 如前所述,富文本的示例包括PDF,PowerPoint,Lotus WordPro,Microsoft Word等。

    重要的是要了解流文件与数据库文件或源物理文件不同。 因为数据库和源物理文件是面向记录的,而流文件是面向字节的。 OmniFind目前不支持使用IFS路径索引流文件以外的对象类型。

    IFS提供了有关IBM i上所有信息的集成结构。 引用“ IFS文件”是一种常见的错误陈述。 由于IFS包含所有内容,并且系统上有许多不同类型的文件,因此“ IFS文件”没有太多含义。 在大多数情况下,使用表达式时,实际上是指使用IFS访问的流文件。 我们的新程序和文档通常同时使用术语“ IFS”和“流文件”,以避免混淆。

    有关Steam文件的更多信息,请参见信息中心 。

    存储过程和结果集

    通过SQL存储过程提供了新的管理和搜索功能。 设计易于从应用程序调用并且足够灵活以允许IBM将来支持其他对象类型的接口非常重要。 由于许多IBM i开发人员都熟悉存储过程,因此SQL过程调用是自然的解决方案。

    SQL结果集提供了一种用于处理搜索结果的便捷机制。 执行搜索时,包含搜索结果SQL结果集将从搜索过程返回到应用程序。 结果集方法允许DB2代表应用程序有效地管理存储,并允许应用程序使用现有的DB2接口(例如JDBC,ODBC或嵌入式SQL)来检索结果并使用结果。

    图1:搜索过程结果集

    创建文本搜索集合

    在开始建立索引和搜索之前,我们需要创建一个文本搜索集合。 文本搜索集合是一个SQL架构,其中包含用于跟踪索引对象的表以及用于管理和搜索索引SQL过程。

    通过调用SYSPROC.SYSTS_CRTCOL存储过程来执行创建文本搜索集合的操作。

    CALL SYSPROC.SYSTS_CRTCOL(‘COLLECTION_FOR_NICK');

    上面的调用将导致在系统上创建SQL模式'COLLECTION_FOR_NICK'。 该模式包含与文本搜索集合关联的所有DB2对象。 这包括目录和管理程序。 文本搜索索引数据存储在集成文件系统中的DB2外部,这与常规DB2文本搜索索引非常相似。

    图2显示了文本搜索集合

    create collection过程具有几个有趣的选项,这些选项反映了用于创建DB2文本搜索索引的选项。 该过程的界面允许我们配置更新频率,语言,文本格式和CCSID。 《 OmniFind扩展用户指南》中详细描述了每个选项的语法。

    例如,如果我想创建自己的收藏集以便每天午夜更新一次,则可以通过以下方式创建我的文本搜索收藏集:

    CALL SYSPROC.SYSTS_CRTCOL(‘COLLECTION_FOR_NICK', ‘UPDATE FREQUENCEY D(*) H(0) M(0)');

    用于管理集合的所有过程都是在SQL模式中创建的。 这允许将权限授予其他用户,以便他们可以搜索文本搜索集合或对其进行更新。

    SET CURRENT SCHEMA COLLECTION_FOR_NICK; GRANT EXECUTE ON PROCEDURE SEARCH(VARCHAR) TO DILBERT;

    设置当前集合的路径

    因为管理过程是在文本搜索集合中创建的(除了SYSPROC中的create和drop集合),所以可以使用SQL路径指定我们正在使用的文本搜索集合。

    SET CURRENT PATH COLLECTION_FOR_NICK;

    这避免了使用模式明确限定每个过程调用的需要。 为简单起见,本文中的其他示例将假定路径设置为上述值。

    添加对象集

    创建文本搜索集合后,OmniFind需要知道要索引哪些对象。 对象集定义在更新过程中将包含在文本索引中的一组对象。

    OmniFind扩展支持两种类型的对象集。

    在输出队列中假脱机文件 特定IFS目录中的IFS流文件

    添加对象集不会使用该对象集中的文本数据更新索引。 OmniFind将在下一次更新期间使用这些对象中的文本更新索引,这将在调用UPDATE存储过程或计划的更新运行时发生。

    添加假脱机文件对象集

    创建ADD_SPLF_OBJECT_SET过程是为了在创建文本搜索集合时添加假脱机文件对象集。 实际上,该过程有许多不同版本,我们可以使用其中任何一个来选择要索引的假脱机文件。

    例如,此过程将为输出队列NTL / MYOUTQ中的所有后台打印文件添加一个后台打印文件对象集:

    CALL ADD_SPLF_OBJECT_SET(‘NTL', ‘MYOUTQ');

    稍有不同的调用将为NTL拥有的所有假脱机文件添加一个对象集:

    CALL ADD_SPLF_OBJECT_SET(‘', ‘', ‘NTL');

    在上面的示例中,空字符串用于输出队列库和队列名称,以指示考虑将任何输出队列中的假脱机文件用于索引。 在同一集合中有多个对象集,并且在多个集合中存在相同对象的情况下,这也很好。 使用包含所有受支持参数的过程版本,可能会出现更复杂的示例。

    本示例索引使用用户数据“ MYAPP”创建并于2010年创建的假脱机文件:

    CALL ADD_SPLF_OBJECT_SET(‘', -- library ‘', -- queue name ‘', -- user name ‘', -- job name ‘', -- job user '', -- job number 'MYAPP', -- user data '2010-01-01T00:00:00', -- start time '2011-01-01T00:00:00' -- end time );

    《 OmniFind扩展用户指南》包含每个参数的完整语法和说明。

    添加IFS流文件对象集

    添加IFS流文件对象集是通过ADD_IFS_STMF_OBJECT_SET过程完成的。 假设我要在主目录“ / home / ntl”中为流文件添加一个对象集

    CALL ADD_IFS_STMF_OBJECT_SET(‘/home/ntl');

    如果这些文件中的一些是富文本格式(Word,PowerPoint,PDF等),那么我将需要使用FORMAT INSO选项创建集合 。

    CALL SYSPROC.SYSTS_CRTCOL(‘COLLECTION_FOR_NICK', ‘FORMAT INSO');

    INSO格式表示更新过程将分析文档(INSide Out),以确定正在索引的文档数据类型。 额外的处理将减慢索引处理的速度-但会提供更大的灵活性。

    OmniFind不会在对象集中隐式包含子目录,但是可以添加任意数量的目录作为唯一对象集。

    将假脱机文件对象集和IFS流文件对象集都放在同一集合中是没有问题的。 搜索的结果集将包含对象类型信息,使应用程序可以根据对象类型过滤结果。

    更新收藏

    在执行更新之前,不会索引集合中包含的对象集。 这可以是在调用SYSPROC.SYSTS_CRTCOL时配置的计划更新,也可以是通过调用UPDATE存储过程进行的手动更新。

    CALL UPDATE;

    更新处理将确定系统上哪些对象是新对象或已更改对象,并为这些对象的文本数据建立索引。 初始更新后的更新是增量的,已建立索引的未更改对象将不会再次建立索引。 在每个更新过程的开始花费一些处理时间来确定已创建,删除或更改了哪些对象。

    UPDATE完成后,现在可以搜索集合了。

    搜索收藏

    通过调用SEARCH存储过程来搜索集合。 搜索表达式的工作方式与我们大多数人熟悉的Web搜索语法非常相似。 IBM InfoCenter中记录了一些高级功能,供那些需要更多高级功能的程序员使用-但基本语法很直观。

    CALL SEARCH(‘database OR DB2');

    结果集将返回到包含结果的客户端应用程序,最相关的结果将首先排序。

    通过从IBM System i Navigator的Run SQL Scripts调用SEARCH可以很容易地查看结果集。 结果集将显示为窗口底部的选项卡。

    图3显示了导航器输出

    应用程序可以通过任何支持结果集SQL接口(嵌入式SQL,JDBC等)访问结果集。 我们提供了一个示例 ,演示了如何使用JDBC连接到数据库,执行搜索以及使用检索到的数据定位对象。

    对象信息

    结果集中最有趣的列是OBJINFOR列,其中包含索引对象的位置。 之所以选择XML作为此列的数据类型,是因为XML具有灵活的结构,还因为可以使用多种工具和解析器来处理XML数据。

    XML是人类可读的,例如,匹配的假脱机文件位置可能看起来像下面所示的清单1。

    清单1:假脱机文件对象信息
    <Spool_File xmlns=”http://www.ibm.com/xmlns/prod/db2textsearch/obj1”> <job_name>QPADEV000C</job_name> <job_user_name>USERA</job_user_name> <job_number>009907</job_number> <spool_file_name>DSXSVRALS</spool_file_name> <spool_file_number>1</spool_file_number> <job_system_name>ZD21BP1</job_system_name> <create_date>1081027</create_date> <create_time>035554</create_time> </Spool_File>

    一个典型的IFS流文件位置可能类似于下面的清单2。

    清单2:流文件对象信息
    <Stream_File xmlns=”http://www.ibm.com/xmlns/prod/db2textsearch/obj1”> <file_path>/home/usera/a.xml</file_path> </Stream_File>

    处理结果集

    结果集可以包含带有假脱机文件和流文件的位置值的行。 不需要将搜索限制为特定的对象类型。

    DB2 for i不提供使用XPath表达式将XML数据转换为关系数据SQL XMLTABLE内置表功能,但是用于解析和处理XML数据的工具可广泛用于宿主语言。 我们的示例显示了一种使用Java处理XML数据的方法。

    结果集包含其他一些包含有用信息的列

    修改时间( MODIFY_TIME ) 对象类型( OBJTYPE ) 对象属性( OBJATTR ) 包含对象库( CONTAINING_OBJECT_LIB ) 包含对象名称( CONTAINING_OBJECT_NAME ) 得分值( SC )

    这些列提供有关搜索结果的其他信息,并且应用程序可以使用它们来过滤结果。 在《 OmniFind扩展用户指南》中对其进行了详细描述。

    附加程序

    我们已经介绍了基本的过程接口,但是还有其他一些值得在OmniFind Extensions用户指南中进行检查的接口。 存在程序

    查询已建立索引的对象的状态, 查询索引的状态, 查询对象集, 删除对象集,或 从系统中删除文本搜索集合。

    样品申请

    我们的示例程序执行文本搜索集合的搜索。 由于Java和JDBC的流行性和平台独立性,我们选择使用它们。 对于其他语言和环境,也可以使用类似的方法,但是这种方法相对容易解释。

    环境设定

    在运行程序之前,我们必须创建文本搜索集合并更新数据。 我们将设置集合,以使其每十五分钟更新一次。 对于此示例,我们希望所有流文件都位于IFS目录/home/ntl ,并且输出队列NTL/MYOUTQ中的所有假脱机文件NTL/MYOUTQ包括索引。

    创建一个文本搜索集合。 CALL SYSPROC.SYSTS_CRTCOL( 'COLLECTION_FOR_NICK', 'UPDATE FREQUENCY D(*) H(*) M(0, 15, 30, 45)'); 将路径/架构设置为当前集合。 SET CURRENT SCHEMA COLLECTION_FOR_NICK; SET CURRENT PATH COLLECTION_FOR_NICK; 将假脱机文件对象集添加到集合中。 CALL ADD_SPLF_OBJECT_SET('NTL', 'MYOUTQ'); 将IFS流文件对象集添加到集合中。 CALL ADD_IFS_STMF_OBJECT_SET('/home/ntl'); 更新集合。 CALL UPDATE;

    由于收集将定期进行更新,因此步骤e中的更新不是严格必需的,但是在此处强制执行更新意味着我们知道在发出搜索之前更新已完成。

    创建基础结构并完成更新过程后,我们可以从集合中搜索关键字。

    用Java调用SEARCH存储过程

    清单3中的Java语句显示了如何编写Java代码来调用SEARCH存储过程。 关键是使用JDBC java.sql.CallableStatement类。 布尔结果用于指示已返回结果集。

    清单3:用Java调用SEARCH存储过程
    // Variable keywords is the words you want to search for. String searchSQL = "CALL COLLECTION_FOR_NICK.SEARCH('" + keywords + "')"; // Create CallableStatement for calling a stored procedure. // Variable connection is a java.sql.Connection instance. CallableStatement cstmt = connection.prepareCall(searchSQL); // The execute method returns a Boolean to indicate that a // result set has been returned boolean isResultSetReturned = cstmt.execute();

    调用SEARCH后检索结果集

    调用SEARCH存储过程之后,我们可以从CallableStatement检索结果集。 对于每一行,我们将使用JDBC ResultSet.getString()函数以String ResultSet.getString()获取OBJECTINFOR列的值。 这样,我们可以遍历结果集,并获取每个对象的位置信息的XML值(作为字符串)。

    清单4:调用SEARCH后获取结果集
    // Get the result set from CallableStatement object ResultSet rs = cstmt.getResultSet(); // The ResultSet next method is used to iterate over // the rows of a ResultSet. // The next method must be called once before the // first data is available for viewing. As long as next // returns true, there is another row of data that // can be used. while (rs.next()) { String objectinfor = rs.getString("objectinfor"); /** Process the object information using the XML string here **/ }

    提取XML对象信息

    XML对象信息包含索引对象的位置信息。 为了使用对象,我们需要提取数据。

    DocumentBuilder类提供了一种从字节流构建XML文档树的方法。 一旦从对象信息构建了文档树,就可以提取特定元素的值。

    本示例说明如何从假脱机文件的对象信息中提取“ job_name”元素的值。

    完整的清单包含一个过程parseObjectInfo ,该过程显示了如何编写代码来处理每种对象类型的信息,并将信息转储到标准输出中。

    清单5:提取XML信息
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; Document doc = null; factory = DocumentBuilderFactory.newInstance(); builder = factory.newDocumentBuilder(); InputStream is = new ByteArrayInputStream(objectinfor.getBytes()); doc = builder.parse(is); String job_name = doc.getElementsByTagName("job_name"). item(0).getTextContent();

    完成程序以进行搜索

    此清单包含完整的程序。 特别令人感兴趣的是我们创建的parseObjectInfo函数,用于处理不同的受支持对象类型. 此函数会将对象的信息转储到标准输出流。 经过一些调整,此处的代码可以执行其他功能,例如从对象中检索文本数据。

    清单6:搜索程序的完整清单
    /// // // ISVSearch example. This program uses the native JDBC driver for the // Developer Kit for Java to call Omnifind stored procedure SEARCH to query // specific key words // // Command syntax: // ISVSearch <collection name> <key words> // // Before calling this program, user should create collection, add // object set to collection, update collecton first. These steps are // used to make the collection searchable. Reference to user documentation // for detail statements. // // This source is an example of how to invoke stored procedure SEARCH // in java code and how to analyze the result. // /// // Include any Java classes that are to be used. In this application, // many classes from the java.sql package are used and the // java.util.Properties class is also used as part of obtaining // a connection to the database. // java.io and javax.xml package are used // to parse the XML column of returned result set of SEARCH stored procedure import java.io.*; import java.sql.*; import java.util.Properties; import javax.xml.parsers.*; import org.w3c.dom.Document; import org.xml.sax.SAXException; //Create a public class to encapsulate the program. public class ISVSearch { // The connection is a private variable of the object. private Connection connection = null; public static void main(String args[]) { // Create an object of type ISVSearch. This // is fundamental to object-oriented programming. Once // an object is created, call various methods on // that object to accomplish work. // In this case, calling the constructor for the object // creates a database connection that the other // methods use to do work against the database. ISVSearch isvSearch = new ISVSearch(); // The search method is called next. This method // processes an Omnifind search statement against the collection // created before. The output of that query is output to standard // out for you to view. isvSearch.search(args[0], args[1]); // Finally, the cleanup method is called. This method // ensures that the database connection that the object has // been hanging on to is closed. isvSearch.cleanup(); } public ISVSearch() { // Following statements were used to create a connection to // DB2 for i Properties properties = new Properties(); properties.put("user", "omnifind"); properties.put("password", "textsearch"); try { Class.forName("com.ibm.db2.jdbc.app.DB2Driver"); connection = DriverManager.getConnection("jdbc:db2:*local", properties); } catch (Exception e) { System.out.println("Caught exception: " + e.getMessage()); } } /** * Search key words from specific collection. * The result will be printed to standard output. * * @param collection The collection name user created * @param keywords The key words user want to search */ public void search(String collection, String keywords) { try { // Constructed the SQL statement to do search // The SQL statement should be like this // CALL <COLLECTIONNAME>.SEARCH('keywords') String searchSQL = "CALL " + collection + ".SEARCH('" + keywords + "')"; // Create CallableStatement for calling a stored procedure. CallableStatement cstmt = connection.prepareCall(searchSQL); // The execute method returns a boolean to indicate the form // of the first result boolean isResultSetReturned = cstmt.execute(); // Check if there is ResultSet returned if (isResultSetReturned) { // GEt the result set from CallableStatement object ResultSet rs = cstmt.getResultSet(); // The ResultSet next method is used to process the rows of a // ResultSet. The next method must be called once before the // first data is available for viewing. As long as next returns // true, there is another row of data that can be used. while (rs.next()) { // The result set returned from SEARCH has columns // OBJTYPE, OBJATTR, CONTAINING_OBJECT_LIB, // CONTAINING_OBJECT_NAME // OBJECTINFOR, MODIFY_TIME, SC String objtype = rs.getString("objtype"); String objattr = rs.getString("objattr"); String containing_object_lib = rs .getString("containing_object_lib"); String containing_object_name = rs .getString("containing_object_name"); // OBJECTINFOR is an XML column which contains all the // detail info about the indexed object. String objectinfor = rs.getString("objectinfor"); Timestamp modify_time = rs.getTimestamp("modify_time"); // Score can help user do better ordering double sc = rs.getDouble("sc"); // parseObjectInfo is used to parse XML column and output parseObjectInfo(objtype, objattr, objectinfor); } } } catch (SQLException e) { // Display more information about any SQL exceptions that are // generated as output. System.out.println("SQLException exception: "); System.out.println("Message:....." + e.getMessage()); System.out.println("SQLState:...." + e.getSQLState()); System.out.println("Vendor Code:." + e.getErrorCode()); e.printStackTrace(); } } /** * Parse object infor XML content to text format and print it to standart * output Based on different object type and attribute, there are different * way to do parsing. * * @param objtype * @param objattr * @param objectinfor */ public static void parseObjectInfo(String objtype, String objattr, String objectinfor) { // DocumentBuilderFactory creates a factory instance. // It will be used to create document builder then DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // DocumentBuilder class provides function to parse XML document DocumentBuilder builder; // Initialize doc to null. This instance will be initialized then Document doc = null; try { // Initialize DocumentBuilder instance builder = factory.newDocumentBuilder(); // Constructed InputStream instance, which will be used as a // parameter while calling DocumentBuilder.parse function // ByteArrayInputStream is a class implements InputStream. // Since objectinfor variable is string, so use // ByteArrayInputStream class to constructed a InputStream // instance with bytes of objectinfor variable. InputStream is = new ByteArrayInputStream(objectinfor.getBytes()); // parse function is used to parse InputStream to XML Document // object doc = builder.parse(is); } catch (Exception e) { System.out.println("Caught exception: " + e.getMessage()); } if (objtype.equals("*OUTQ ") && objattr.equals("*SPLF ")) { // For the object whose object type is "*OUTQ " and object // attribute is "*SPLF ", // user following way to get the detail value System.out.println("========================================"); // Get text content for element whose tag name is "job_name" or the // other tag. System.out.println("Job name:" + doc.getElementsByTagName("job_name").item(0) .getTextContent()); System.out.println("Job user name:" + doc.getElementsByTagName("job_user_name").item(0) .getTextContent()); System.out.println("Job number:" + doc.getElementsByTagName("job_number").item(0) .getTextContent()); System.out.println("spool file name:" + doc.getElementsByTagName("spool_file_name").item(0) .getTextContent()); System.out.println("spool file number:" + doc.getElementsByTagName("spool_file_number").item(0) .getTextContent()); System.out.println("Job system name:" + doc.getElementsByTagName("job_system_name").item(0) .getTextContent()); // The date format CYYMMDD is defined as follows: // C Century, where 0 indicates years 19xx and 1 indicates years // 20xx. // YY Year // MM Month // DD Day System.out.println("create date:" + doc.getElementsByTagName("create_date").item(0) .getTextContent()); // The time format HHMMSS is defined as follows: // HH Hour // MM Minutes // SS Seconds System.out.println("create time:" + doc.getElementsByTagName("create_time").item(0) .getTextContent()); /* The output should like below ======================================== Job name:QPRTJOB Job user name:NTL Job number:066537 spool file name:QPJOBLOG spool file number:3526 Job system name:RCHASRA5 create date:1110430 create time:152003 */ } else if (objtype.equals("*STMF ") && objattr.equals("*DATA ")) { // For the object whose object type is "*STMF " and object // attribute is "*DATA ", // user following way to get the detail value System.out.println("========================================"); // Get text content for element whose tag name is "file_path" System.out.println("File path:" + doc.getElementsByTagName("file_path").item(0) .getTextContent()); /* The output should like below ======================================== File path:/home/user/test.txt */ } } /** * The following method ensures that any JDBC resources that are still * allocated are freed. */ public void cleanup() { try { if (connection != null) connection.close(); } catch (Exception e) { System.out.println("Caught exception: "); e.printStackTrace(); } } }

    清单7:示例输出

    注意:这假定一个假脱机文件和一个IFS流文件与搜索关键字匹配。

    ======================================== Job name:QPRTJOB Job user name:NTL Job number:066537 spool file name:QPJOBLOG spool file number:3526 Job system name:RCHASRA5 create date:1110430 create time:152003 ======================================== File path:/home/ntl/test.txt

    结论

    现在,您应该了解如何使用新的OmniFind Extension存储过程执行以下操作:

    创建文本搜索集合 在IFS中添加一个或多个假脱机文件或流文件的对象集 更新索引 执行搜索

    这些新的IBM i搜索功能提供了一种可以轻松增强应用程序功能的解决方案。 加上编写实用程序的简单方法,这些实用程序可以快速找到系统上的各种对象。 OmniFind V1R2可免费用于IBM i 7.1。

    翻译自: https://www.ibm.com/developerworks/ibmi/library/i-omnifind/omnifind.html

    Processed: 0.016, SQL: 9