5

すべて基本クラスから継承するオブジェクトをRavenDbに格納し、マルチマップインデックスを使用して次のようなすべてのサブタイプを検索しています。

public class BaseRequest
{
    public Guid Id { get; set; }
    public string RequestName { get; set; }
    public DateTime RequiredDate { get; set; }
}

public class RequestA: BaseRequest
{
    public string SomethingForA { get; set; }
}

public class RequestB : BaseRequest
{
    public int SomethingForB { get; set; }
}

public class AllRequests: AbstractMultiMapIndexCreationTask
{
    public AllRequests()
    {
        AddMap<RequestA>(requests => from req in requests select new {req.RequestName, req.RequiredDate});
        AddMap<RequestB>(requests => from req in requests select new {req.RequestName, req.RequiredDate });
    }   
}

そして、私はそれを次のように検索します:

    public BaseRequest[] Search(string requestType, string requestName, DateTime? requestDate = null) {
        var q = RavenSession.Query<BaseRequest, AllRequests>();

        if (!string.IsNullOrEmpty(requestName)) {
            q = (IRavenQueryable<BaseRequest>)Queryable.Where(q, x => x.RequestName == requestName);
        }
        if (requestDate.HasValue) {
            q = (IRavenQueryable<BaseRequest>) Queryable.Where(q, x => x.RequiredDate == requestDate);
        }

        return q.ToArray();
    }

私がやりたいのは、リクエストのCLRタイプで結果をさらにフィルタリングすることです。「Raven-Entity-Name」メタデータフィールドを使用してこれを行うことは可能ですか?その場合、どのように行いますか?

などを使用できることはわかってQuery<RequestA>()いますが、後日、複数のタイプでフィルタリングする必要があり、これらのタイプはユーザーによって動的に選択されます。

注:私が本当にやりたいのは、インデックスを使用して、特定のRequestNameが指定されたリクエストをプルバックすることですが、RequestAのみ(後でRequestA、RequestC、およびRequestDのみ)を返します。各タイプを個別に取得するために複数のクエリを実行したくはありません。パラメータによってクエリを実行し、場合によってはタイプする1つのクエリを実行したいと思います。

システムは、リクエストタイプが毎月追加されるように設計されており、おそらく数百の異なるタイプになるでしょう。指定されたパラメータを使用して、特定のタイプのセットを動的に検索したいと思います。

4

2 に答える 2

2

それを解決しました。を使用MetadataFor(req)してclrタイプをインデックスに追加してから、特定のマップタイプを使用してクエリを実行する必要がありました。このような:

public class AllRequests: AbstractMultiMapIndexCreationTask
{
    public class SearchMap {
      public string RequestName{get;set;}
      public DateTime RequiredDate{get;set;}
      public string RequestType{get;set;}
    }

   public AllRequests(){
        AddMap<RequestA>(requests => from req in requests select new {req.RequestName, req.RequiredDate, RequestType = MetadataFor(req)["Raven-Clr-Type"]});
        AddMap<RequestB>(requests => from req in requests select new {req.RequestName, req.RequiredDate, RequestType = MetadataFor(req)["Raven-Clr-Type"] });
    }   
}

次に、リクエストの実際のフィールドに対して、また次のようなタイプでクエリを実行できます。

   public BaseRequest[] Search(string requestType, string requestName, DateTime? requestDate = null) {
        var q = RavenSession.Query<AllRequests.SearchMap, AllRequests>();

        if (!string.IsNullOrEmpty(requestName)) {
            q = (IRavenQueryable<BaseRequest>)Queryable.Where(q, x => x.RequestName == requestName);
        }
        if (requestDate.HasValue) {
            q = (IRavenQueryable<BaseRequest>) Queryable.Where(q, x => x.RequiredDate == requestDate);
        }

        if (!string.IsNullOrEmpty(requestType))
        {
            q =
                q.Where(
                    x =>
                    x.RequestType == GetClrTypeFromPassedInValue(requestType));
        }
        return q.As<BaseRequest>().ToArray();
    }
于 2012-05-22T15:02:16.053 に答える
1

メタデータは単なるフィールドであるため、インデックスが作成されている限り、クエリを実行できます。

組み込みのインデックスRaven/DocumentsByEntityNameは、次のようになります。

database.PutIndex("Raven/DocumentsByEntityName", new IndexDefinition
{
    Map =
        @"from doc in docs 
let Tag = doc[""@metadata""][""Raven-Entity-Name""]
select new { Tag, LastModified = (DateTime)doc[""@metadata""][""Last-Modified""] };",
    Indexes =
    {
        {"Tag", FieldIndexing.NotAnalyzed},
    },
    Stores =
    {
        {"Tag", FieldStorage.No},
        {"LastModified", FieldStorage.No}
    }
});

次に、次のようにクエリできます。

var results = s.Advanced.LuceneQuery<RequestB>()
                .WhereEquals("Tag", "Entity-Name")
                .ToArray();
于 2012-05-22T13:52:43.277 に答える