为什么Lucene IndexWriter在从Web模块调用时没有更新索引?

时间:2016-01-19 15:13:39

标签: java lucene

使用Lucene的Web项目有一个奇怪的问题。 我编写了一个bean,它将业务对象的数据写入Lucene。业务数据由Web前端提供。一切都很好。 但在一些很少的情况下,业务对象不会添加到索引中。似乎这种情况发生在多个用户访问bean的情况下。

我的bean使用静态方法创建Lucene IndexWriter并在我的业务对象的基础上创建Lucene文档。 我认为使所有方法静态足以成为线程保存。但现在我想知道是否有必要使我的更新方法也同步'避免与其他线程冲突? 在没有将对象写入索引的情况下,没有从lucene抛出的异常。所以我不能说我的图层背后会发生什么。

我的更新方法如下所示:

public static boolean updateWorklist(ItemCollection workitem) throws PluginException {

        IndexWriter awriter = null;
        // try loading imixs-search properties
        Properties prop = loadProperties();
        if (prop.isEmpty())
            return false;

        try {
            awriter = createIndexWriter(prop);

            // create term
            Term term = new Term("$uniqueid", workitem.getItemValueString("$uniqueid"));
            // test if document should be indexed or not
            if (matchConditions(prop, workitem)) {
                logger.fine("add workitem '" + workitem.getItemValueString(EntityService.UNIQUEID) + "' into index");
                awriter.updateDocument(term, createDocument(workitem));
            } else {
                logger.fine("remove workitem '" + workitem.getItemValueString(EntityService.UNIQUEID) + "' into index");
                awriter.deleteDocuments(term);
            }
        } catch (IOException luceneEx) {
            // close writer!
            logger.warning(" Lucene Exception : " + luceneEx.getMessage());

            throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
                    "Unable to update search index", luceneEx);

        } finally {

            if (awriter != null) {
                logger.fine(" close writer");
                try {
                    awriter.close();
                } catch (CorruptIndexException e) {
                    throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
                            "Unable to update search index", e);
                } catch (IOException e) {
                    throw new PluginException(LucenePlugin.class.getSimpleName(), INVALID_INDEX,
                            "Unable to update search index", e);
                }

            }
        }

        logger.fine(" update worklist successfull");
        return true;
    }

.....

    public static IndexWriter createIndexWriter(Properties prop)
            throws IOException {

        /**
         * Read configuration
         */
        // String sLuceneVersion = prop.getProperty("Version", "LUCENE_45");

        String sIndexDir = prop.getProperty("lucence.indexDir");
        String sFulltextFieldList = prop
                .getProperty("lucence.fulltextFieldList");
        String sIndexFieldListAnalyse = prop
                .getProperty("lucence.indexFieldListAnalyze");
        String sIndexFieldListNoAnalyse = prop
                .getProperty("lucence.indexFieldListNoAnalyze");

        logger.fine("IndexDir:" + sIndexDir);
        logger.fine("FulltextFieldList:" + sFulltextFieldList);
        logger.fine("IndexFieldListAnalyse:" + sIndexFieldListAnalyse);
        logger.fine("IndexFieldListNoAnalyse:" + sIndexFieldListNoAnalyse);
        // compute search field list
        StringTokenizer st = new StringTokenizer(sFulltextFieldList, ",");
        searchFieldList = new ArrayList<String>();
        while (st.hasMoreElements()) {
            String sName = st.nextToken().toLowerCase();
            // do not add internal fields
            if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
                searchFieldList.add(sName);
        }

        // compute Index field list (Analyze)
        st = new StringTokenizer(sIndexFieldListAnalyse, ",");
        indexFieldListAnalyse = new ArrayList<String>();
        while (st.hasMoreElements()) {
            String sName = st.nextToken().toLowerCase();
            // do not add internal fields
            if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
                indexFieldListAnalyse.add(sName);
        }

        // compute Index field list (Analyze)
        st = new StringTokenizer(sIndexFieldListNoAnalyse, ",");
        indexFieldListNoAnalyse = new ArrayList<String>();
        while (st.hasMoreElements()) {
            String sName = st.nextToken().toLowerCase();
            // do not add internal fields
            if (!"$uniqueid".equals(sName) && !"$readaccess".equals(sName))
                indexFieldListNoAnalyse.add(sName);
        }

        /**
         * Now create a IndexWriter Instance
         */
        Directory indexDir = createIndexDirectory(prop);

        Analyzer analyzer = new StandardAnalyzer();
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(
                Version.LATEST, analyzer);

        // set the WriteLockTimeout to wait for a write lock (in milliseconds)
        // for this instance. 10 seconds!
        indexWriterConfig.setWriteLockTimeout(10000);

        return new IndexWriter(indexDir, indexWriterConfig);
    }

....

public static boolean matchConditions(Properties prop, ItemCollection aworktiem) {

    String typePattern = prop.getProperty("lucence.matchingType");
    String processIDPattern = prop.getProperty("lucence.matchingProcessID");

    String type = aworktiem.getItemValueString("Type");
    String sPid = aworktiem.getItemValueInteger("$Processid") + "";

    // test type pattern
    if (typePattern != null && !"".equals(typePattern) && !type.matches(typePattern)) {
        logger.fine("Lucene type '" + type + "' did not match pattern '" + typePattern + "'");
        return false;
    }

    // test $processid pattern
    if (processIDPattern != null && !"".equals(processIDPattern) && !sPid.matches(processIDPattern)) {
        logger.fine("Lucene $processid '" + sPid + "' did not match pattern '" + processIDPattern + "'");

        return false;
    }
    return true;
}

.... 编辑20.Jan: 我在代码示例中添加了IndexWriter方法。我的属性文件为空,并未向IndexWriter提供任何lucene设置

编辑21.Jan: 我添加了matchConditions方法

1 个答案:

答案 0 :(得分:0)

正如@ maksim07所解释的,我实现的问题是使用静态变量和方法。因此,createDocument方法可以观察到空的searchFieldList,indexFieldListAnalyse,indexFieldListNoAnalyse集合,因为存在竞争条件。

最后,我通过使用单独的模式和单独的init()方法重新实现了代码,其中我初始化了我的成员变量的所有值。 使用Singleton EJB可以非常轻松地使用单例模式,并保证所有方法调用都通过EJB容器的默认行为进行同步。