3

私は単純なタイプを持っていますQuestion

public class Question
{
    public Question(string id)
    {
        Id = id;
        Tags = new List<string>();
    }

    public string Id { get; private set; }
    public IList<string> Tags { get; set; }            
}

私はそのような質問のサンプルコレクションを定義しました:

var q1 = new Question("q1") { Tags = new List<string>() {"a"} };
var q2 = new Question("q2") { Tags = new List<string>() {"b"} };
var q3 = new Question("q3") { Tags = new List<string>() {"a", "b", "c"} };
var q4 = new Question("q4") { Tags = new List<string>() {"a", "b"} };
var q5 = new Question("q5") { Tags = new List<string>() {"z"} };
var q6 = new Question("q6");
var questions = new List<Question>() {q1, q2, q3, q4, q5, q6};

次に、指定されたサブセットから、少なくとも1つのタグを含むすべての質問を見つける必要があります。サブセットは以下に定義されています。

string[] tags = new[] {"a", "b"};

q1q2q3q4が返されることを期待しています。目的の結果を得るために使用するクエリは次のとおりです。

var questions = DocumentSession.Query<Question>().AsQueryable();
questions = GetQuestionsToContainingAtLeastOneTagFromSubset(questions, tags)
// some other query restrictions
var result = questions.ToList(); // (**)

私のコレクションに制限を課すことを想定している関数は次のとおりです。

private IQueryable<Question> GetQuestionsToContainingAtLeastOneTagFromSubset(IQueryable<Question> questions, IEnumerable<string> tags)
{
    var result = new List<Question>();
    foreach (var tag in tags)
    {
        var currentTag = tag;
        var resultForTag = questions.Where(x => x.Tags.Any(xTag => xTag == currentTag));
        result = result.Concat(resultForTag).ToList();
     }
     return result.GroupBy(x => x.Id).Select(grp => grp.First()).AsQueryable();
}

これは非常に非効率的だと思います。.ToList()提供されている関数内での使用は避けたいです。私が理解しているように、この.ToList()式はRavenDBにクエリを実行し、部分的な結果を返します(BTW:私は正しいですか?)。これは効率的ではありません。提供された関数に制限を課し、すべての制限が課された後にクエリを実行したいだけです。この(**)場所は、バッチをRavenDB取得クエリ結果に送信するのに適しています。

それを改善する方法は?

4

2 に答える 2

0

このコードを試してください:

 var q1 = new Question("q1") { Tags = new List<string>() {"aa", "bb"} };
 var q2 = new Question("q2") { Tags = new List<string>() {"aa"} };
 var q3 = new Question("q3") { Tags = new List<string>() {"aa", "bb", "cc"} };
 var q4 = new Question("q4");
 var questions = new List<Question>() {q1, q2, q3, q4};
 string[] tags = new[] { "bb", "cc" };

 var res = (from p in questions where 
           (from q in tags where p.Tags.Contains(q) == true select p).ToArray().Count() >= 1 
            select p).Distinct(); 
 //If you want more speed you can try to add .AsParallel() after .Distinct()
于 2012-04-13T08:54:58.620 に答える
0

lucene にクエリを実行して、次のようなタグ配列配列に一致するタグを使用して質問を取得できます。

string[] tags = new[] { "a", "b" };
string queryRange = "(" + string.Join(" OR ", tags) + ")";

var res = session.Advanced.LuceneQuery<Question>()
               .Where("Tags:" + queryRange).ToList();

これは、サブセットではなく、索引付けされた質問全体を照会することに注意してください。しかし、追加できると思います-私は推測します-クエリ文字列式に。この種のクエリの詳細については、Lucene のドキュメントを参照してください: http://lucene.apache.org/core/old_versioned_docs/versions/3_0_0/queryparsersyntax.html

于 2012-04-13T11:18:48.370 に答える