私たちはRavenを使用してログインを検証し、人々が私たちのサイトにアクセスできるようにしています。
私たちが見つけたのは、これを行うと次のようになります。
// Context is an IDocumentSession
Context.Query<UserModels>()
.SingleOrDefault(u => u.Email.ToLower() == email.ToLower());
クエリは、Ravenのドキュメントの最初の128個のドキュメントのみをフィルタリングします。私たちのデータベースには数千があります、それであなたの電子メールがたまたま最初に返された128にない限り、あなたは運が悪いです。
Ravenのサンプルコードもネット上で出会ったサンプルコードも、Skip()とTake()を使用してループを実行してセットを反復処理することはありません。
- これはレイヴンの望ましい行動ですか?
- 高度なLuceneクエリを使用しても同じ動作ですか?すなわち; 高度なクエリの動作は異なりますか?
- 以下の解決策は適切ですか?少し醜いですね。: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を使用しており、期待どおりに機能しています。