【问题标题】:Lucene.net Negation clause is not workingLucene.net 否定子句不起作用
【发布时间】:2016-03-25 12:08:59
【问题描述】:

我对 Lucene.net 非常陌生,虽然我无法实现基本功能,即不在。

我的要求是搜索“road?construction”,不带“Works”字样。

例如

主要道路建设工程 -- 无效

道路建设和维护服务 -- 有效(不包含 Works)

请参考下面我的代码。

string searchQuery = "\"road?construction\"*";
    BooleanQuery query2 = new BooleanQuery();
    Query query;
                try
                {
                    query = parser.Parse(searchQuery.Trim());
                }
                catch (ParseException)
                {
                    query = parser.Parse(QueryParser.Escape(searchQuery.Trim()));
                }
                            
                query2.Add(query,Occur.SHOULD);
                query2.Add(new BooleanClause(new TermQuery (new Term("Name", "Works")), Occur.MUST_NOT));

这仍然会将上述两个记录都输入到搜索结果中。我希望删除无效记录(首先)。

这是后端生成的查询结果。

请提出解决方法。

提前致谢。

【问题讨论】:

    标签: full-text-search lucene.net


    【解决方案1】:

    不知道为什么您将通配符放入短语中。如果您正在寻找“道路建设”,那么这就是您所需要的。如果您希望允许一些变化,那么您可能需要一个“草率的短语”,即。 “道路建设”~2。数字部分允许 n 个“操作”,例如中间的 n 个附加词。

    这里有一组测试显示您的示例(TestExpr2、TestExpr3)和一些工作变体(TestExpr1 和 TestQuery)。

    希望对你有帮助

    [TestClass]
    public class UnitTest7
    {
        [TestMethod]
        public void TestExpr1()
        {
            TestExpr("\"road construction\" -works");
        }
        [TestMethod]
        public void TestExpr2()
        {
            TestExpr("\"road?construction\"* -works");
        }
        [TestMethod]
        public void TestExpr3()
        {
            TestExpr(QueryParser.Escape("\"road?construction\"* -works"));
        }
    
        private void TestExpr(string expr)
        {
            var writer = CreateIndex();
            Add(writer, "Main Road Construction Works");
            Add(writer, "Road Construction And Maintenance Services");
            writer.Flush(true, true, true);
            var searcher = new IndexSearcher(writer.GetReader());
    
            var result = Search(searcher, expr);
    
            Assert.AreEqual(1, result.Count);
            Assert.IsTrue(result.Contains("Road Construction And Maintenance Services"));
            writer.Dispose();
        }
    
        [TestMethod]
        public void TestQuery()
        {
            var writer = CreateIndex();
            Add(writer, "Main Road Construction Works");
            Add(writer, "Road Construction And Maintenance Services");
            writer.Flush(true, true, true);
            var searcher = new IndexSearcher(writer.GetReader());
    
            var query = new BooleanQuery();
            var p = new PhraseQuery();
            p.Add(new Term("name", "road"));
            p.Add(new Term("name", "construction"));
            query.Add(p, Occur.MUST);
            query.Add(new TermQuery(new Term("name", "works")), Occur.MUST_NOT);
    
            var result = Search(searcher, query);
    
            Assert.AreEqual(1, result.Count);
            Assert.IsTrue(result.Contains("Road Construction And Maintenance Services"));
            writer.Dispose();
        }
    
        private List<string> Search(IndexSearcher searcher, string expr)
        {
            var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
            var queryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "name", analyzer);
            var query = queryParser.Parse(expr);
            return Search(searcher, query);
        }
    
        private List<string> Search(IndexSearcher searcher, Query query)
        {
            var collector = TopScoreDocCollector.Create(10, true);
            searcher.Search(query, collector);
            var result = new List<string>();
            var matches = collector.TopDocs().ScoreDocs;
            foreach (var item in matches)
            {
                var id = item.Doc;
                var doc = searcher.Doc(id);
                result.Add(doc.GetField("name").StringValue);
            }
    
            return result;
        }
    
        IndexWriter CreateIndex()
        {
            var directory = new RAMDirectory();
            var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
            var writer = new IndexWriter(directory, analyzer, new IndexWriter.MaxFieldLength(1000));
            return writer;
        }
    
        void Add(IndexWriter writer, string text)
        {
            var document = new Document();
            document.Add(new Field("name", text, Field.Store.YES, Field.Index.ANALYZED));
            writer.AddDocument(document);
        }
    }
    

    【讨论】:

    • 抱歉,安迪回复晚了。你提供了很好的解释。它真的帮助了我。我当前搜索的一个问题是,当我搜索“道路建设”时,它也应该搜索“道路建设”(两者都相同)。如何做到这一点?
    • 使用像"road construction"~2这样的“废话”查询。这允许对短语中的术语进行 2 次“操作”。因此,两者之间可能有 2 个术语或重新排序和 1 个术语。有点像和“AND”(带有 MUST 的 BooleanQuery),但定义了术语需要有多“接近”。根据需要增加 2。但是你不应该让它太大,否则你会开始得到意想不到的结果。
    • “道路建设”~3 为我工作。非常感谢安迪。你是头脑大师。
    • 还有一个问题,如何控制Lucene提供的Rank?我的问题是有时 lucene 没有得到更重要的结果。我听说过提升,但对它了解不多。谢谢。
    • 现在你问的是难题!!订购通常是一个“问题”。但是,你如何定义什么是“重要的”?这对人类来说似乎很明显,但实际上很难创建一个好的算法。有几个选项可用:blog.imaginea.com/understanding-lucene-boosting-part-1 是对 boost 的一个很好的解释。 stackoverflow.com/questions/9829161/… 是代码中的示例;或者在索引时创建一个“分数”,在查询时使用一个Sort;或按日期排序(如果这很重要)。或者检索很多文档然后对它们进行排序;或者...
    猜你喜欢
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 2014-01-26
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多