7

私たちはRavenを使用してログインを検証し、人々が私たちのサイトにアクセスできるようにしています。

私たちが見つけたのは、これを行うと次のようになります。

// Context is an IDocumentSession 
Context.Query<UserModels>()
           .SingleOrDefault(u => u.Email.ToLower() == email.ToLower()); 

クエリは、Ravenのドキュメントの最初の128個のドキュメントのみをフィルタリングします。私たちのデータベースには数千があります、それであなたの電子メールがたまたま最初に返された128にない限り、あなたは運が悪いです。

Ravenのサンプルコードもネット上で出会ったサンプルコードも、Skip()とTake()を使用してループを実行してセットを反復処理することはありません。

  1. これはレイヴンの望ましい行動ですか?
  2. 高度なLuceneクエリを使用しても同じ動作ですか?すなわち; 高度なクエリの動作は異なりますか?
  3. 以下の解決策は適切ですか?少し醜いですね。:P

私の解決策は、null以外の結果が発生するまですべてのドキュメントのセットをループしてから、中断して戻ることです。

public T SingleWithIndex(string indexName, Func<T, bool> where)
{
    var pageIndex = 1;
    const int pageSize = 1024;
    RavenQueryStatistics stats;

var queryResults = Context.Query<T>(indexName)
    .Statistics(out stats)
    .Customize(x => x.WaitForNonStaleResults())
    .Take(pageSize)
    .Where(where).SingleOrDefault();

if (queryResults == null && stats.TotalResults > pageSize)
{
    for (var i = 0; i < (stats.TotalResults / (pageIndex * pageSize)); i++)
    {
        queryResults = Context.Query<T>(indexName)
            .Statistics(out stats)
            .Customize(x => x.WaitForNonStaleResults())
            .Skip(pageIndex * pageSize)
            .Take(pageSize)
            .Where(where).SingleOrDefault();

        if (queryResults != null) break;

        pageIndex++;
    }

}

return queryResults;

}

編集:

以下の修正を使用しても、クエリパラメータがRavenDBインスタンスに渡されません。理由はまだわかりません。

Context.Query<UserModels>()
    .Where(u => u.Email == email)
    .SingleOrDefault();

結局、私はlinqクエリの代わりにAdvanced Lucene Syntaxを使用しており、期待どおりに機能しています。

4

1 に答える 1

4

RavenDBはを理解しないためSingleOrDefault、フィルターなしでクエリを実行します。次に、条件が結果セットに対して実行されますが、デフォルトでは、Ravenは最初の128個のドキュメントのみを返します。代わりに、電話する必要があります

Context.Query<UserModels>()
       .Where(u => u.Email == email)
       .SingleOrDefault();

したがって、フィルタリングはRavenDB/Luceneによって行われます。

于 2011-02-24T13:14:29.303 に答える