【问题标题】:How can i filter my data by foreign key before lucene searching?如何在 lucene 搜索之前通过外键过滤我的数据?
【发布时间】:2013-02-08 08:01:46
【问题描述】:

我想在我的项目中使用 Lucene 搜索,因为它很快,但是有一个问题。

我有数据库表用户和友谊。我想通过搜索表单找到用户的朋友。使用 lucene 我只能通过搜索查询找到所有用户,获取他们的 id,将他们放到实体框架中,然后只获取用户的朋友,但是如果系统中的用户有一千万,而该用户的朋友只有几个呢?所以我需要带用户的朋友,然后通过搜索查询过滤他们。我怎样才能做到这一点?我听说过 Linq to Lucene,但我不确定它是否是我需要的。请帮我解决我的麻烦。

附:对不起我的英语,我来自乌克兰,英语说得不好:)

我找到了解决方案。我会将好友 ID 存储在索引中,并通过这些 ID 查找用户好友。这不是最好的解决方案,因为索引会经常被编辑,但我无法实现另一个想法。

【问题讨论】:

  • 如果一个用户只有几个朋友,那么你为什么要索引这些用户呢?如果我是你,我会首先尝试使用某种在线搜索(例如,获取朋友列表并遍历他们)。你试过这样的事情吗?
  • 嗯...嗯,也许你是对的。但是如果用户有 1 万个朋友呢?
  • 比你的问题成立,你可以开始祈祷有人会给你一个有用的答案。

标签: c# .net linq entity-framework lucene.net


【解决方案1】:

这可以通过使用filters 来完成。这是一个简短的演示,它将结果限制为仅具有 FriendsWith:Beta 的那些文档。这将需要重新索引 受更改的友谊关系影响的文档。 TermsFilter 类可以在 contrib 包中找到。

using System;
using System.Collections.Generic;
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Directory = Lucene.Net.Store.Directory;
using Version = Lucene.Net.Util.Version;

namespace ConsoleApplication {
    public static class Program {
        public static void Main(string[] args) {
            var directory = new RAMDirectory();
            var analyzer = new KeywordAnalyzer();

            using (var writer = new IndexWriter(directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) {
                var users = new [] { "Alfa", "Beta", "Gamma", "Delta" };
                var friendships = new Dictionary<String, String[]> {
                    { "Alfa", new [] { "Beta", "Gamma", "Delta" } },
                    { "Beta", new [] { "Gamma", "Delta" } },
                    { "Gamma", new [] { "Delta" } },
                    { "Delta", new String[0] } // Noone likes Delta.
                };

                foreach (var userName in users) {
                    var doc = new Document();
                    doc.Add(new Field("Name", userName, Field.Store.YES, Field.Index.NO));

                    foreach (var friendName in friendships[userName]) {
                        doc.Add(new Field("FriendsWith", friendName, Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
                    }

                    writer.AddDocument(doc);
                }

                writer.Commit();
            }

            // This should be the real query provided by the user (city, age, description, ...)
            var query = new MatchAllDocsQuery();

            // Create a filter limiting the result to those being friends with the current user,
            // in this example the user "Beta".
            var filter = new TermsFilter();
            filter.AddTerm(new Term("FriendsWith", "Gamma"));

            var reader = IndexReader.Open (directory, readOnly: true);
            var searcher = new IndexSearcher(reader);

            var result = searcher.Search (query, filter, 10);
            foreach(var topDoc in result.ScoreDocs) {
                var doc = searcher.Doc(topDoc.Doc);
                var foundName = doc.Get ("Name");
                Console.WriteLine("Matched user '{0}'", foundName);
            }

            Console.ReadLine();
        }
    }
}

【讨论】:

    猜你喜欢
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 2023-03-16
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多