7

RavenDbのドキュメントには次のように記載されています。

数値またはGUIDIDプロパティがサポートされており、シームレスに機能します。この場合、RavenDBは、内部文字列IDを、エンティティに表示されている数値またはGUID値に自動的に変換します。

次のオブジェクトを保存しました。

class A
{
    public Guid Id { get; set; }
    public Guid BId { get; set; }
}

class B
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

次に、次のプロジェクションを作成しました。

class AB
{
    public Guid Id { get; set; }       // This should be the Id of A
    public Guid BId { get; set; }      // This should be the Id of B
    public string BName { get; set; }  // This should be the name of B
}

投影を作成するために、次のインデックスを作成しました。

class MyIndex : AbstractIndexCreationTask<AB>
{
    public MyIndex()
    {
        Map = docs =>
            from d in docs
            select new
            {
                d.Id,
                d.BId,
                BName = string.Empty
            };

        TransformResults = (database, results) =>
            from r in results
            let b = database.Load<B>("bs/" + r.BId.ToString())
            select new
            {
                r.Id,
                r.BId,
                BName = b.Name
            };
    }
}

次のクエリを使用する場合:

session.Query<AB, MyIndex>().FirstOrDefault(t => t.Id == guid);

この例外が発生します:

値「bs/cc0a65ae-dd36-4437-8a57-fa20b91eeef7」をタイプ「System.Guid」に変換中にエラーが発生しました。パス'Id'。

質問:

  1. Idこれは、私のGuidではなく、そこにある文字列であるため、私の投影での変換が原因です。ただし、これを省略してもIDは返されません。私は何をしなければなりませんか?

  2. "bs/" + r.BId.ToString()関連するドキュメントをロードするには、文字列の作成を使用する必要があります。これを行う必要がない方法はありますか?docタグを解決するような関数はありますか?

  3. ドキュメントタグを完全に取り除く一般的な方法はありますか?

私の制約。

Guidを生成しますが、RavenDbに生成させることはできません。実際のドキュメントIDは文字列であることは知っていますが、実際には自分で作成したGUIDを使用する必要があります。Id私は自分のエンティティのプロパティを所有したいと思います。

Raven.Client1.0.972を使用しています

4

5 に答える 5

6

MultiMap / Reduce Indexを使用してこれを実現できますが、いくつかのハッカーが必要になります。

1)GUIDではなく、文字列の使用を減らす必要があります。以下で説明するように、ABクラスのGUIDとして値を取り戻すことができます。

2)レイヴンがそれを「__document_id」に変換しようとするため、ABクラスの最初のプロパティを「Id」と呼ぶことはできません。それでそれを「AId」と呼んでください、そしてそれはうまくいくでしょう。

3)マッピングフェーズでは、文字列を自分で操作して、ドキュメントキープレフィックスを取り除く必要があります。

これがすべてをまとめたサンプルプログラムです。これは実際に機能することを示していますが、Ayendeが文字列識別子を好む理由も示しているので、この種の混乱に対処する必要はありません。

using System;
using System.Linq;
using Raven.Client.Document;
using Raven.Client.Indexes;

namespace RavenScratchTest
{
  class Program
  {
    static void Main()
    {
      var documentStore = new DocumentStore { Url = "http://localhost:8080" };
      documentStore.Initialize();
      IndexCreation.CreateIndexes(typeof(Program).Assembly, documentStore);

      using (var session = documentStore.OpenSession())
      {
        var b = new B { Id = Guid.NewGuid(), Name = "Foo" };
        var a = new A { Id = Guid.NewGuid(), BId = b.Id };

        session.Store(a);
        session.Store(b);

        session.SaveChanges();
      }

      using (var session = documentStore.OpenSession())
      {
        var a = session.Query<A>().Customize(x => x.WaitForNonStaleResults()).First();
        var b = session.Query<B>().Customize(x => x.WaitForNonStaleResults()).First();

        Console.WriteLine("A:  Id = {0}", a.Id);
        Console.WriteLine("   BId = {0}", a.BId);
        Console.WriteLine();
        Console.WriteLine("B:  Id = {0}", b.Id);
        Console.WriteLine("  Name = {0}", b.Name);
        Console.WriteLine();

        var guid = a.Id;
        var ab = session.Query<AB, MyIndex>().Customize(x => x.WaitForNonStaleResults())
          .FirstOrDefault(t => t.AId == guid);

        if (ab == null)
          Console.WriteLine("AB: NULL");
        else
        {
          Console.WriteLine("AB:  AId = {0}", ab.AId);
          Console.WriteLine("   BId = {0}", ab.BId);
          Console.WriteLine("   BName = {0}", ab.BName);
          Console.WriteLine();
        }
      }

      Console.WriteLine();
      Console.WriteLine("Done.");
      Console.ReadLine();
    }
  }

  class A
  {
    public Guid Id { get; set; }
    public Guid BId { get; set; }
  }

  class B
  {
    public Guid Id { get; set; }
    public string Name { get; set; }
  }

  class AB
  {
    public Guid AId { get; set; }
    public Guid BId { get; set; }
    public string BName { get; set; }
  }

  class MyIndex : AbstractMultiMapIndexCreationTask<MyIndex.ReduceResult>
  {
    public MyIndex()
    {
      AddMap<A>(docs => from a in docs
                select new
                {
                  AId = a.Id.ToString().Split('/')[1],
                  a.BId,
                  BName = (string)null
                });

      AddMap<B>(docs => from b in docs
                select new
                {
                  AId = (string)null,
                  BId = b.Id.ToString().Split('/')[1],
                  BName = b.Name
                });

      Reduce = results => from result in results
                group result by result.BId
                into g
                select new
                  {
                    g.FirstOrDefault(x => x.AId != null).AId,
                    BId = g.Key,
                    g.FirstOrDefault(x => x.BName != null).BName
                  };
    }

    internal class ReduceResult
    {
      public string AId { get; set; }
      public string BId { get; set; }
      public string BName { get; set; }
    }
  }
}
于 2012-10-02T20:59:50.520 に答える
2

保存時にRavenDBにIDを明示的に指定できます。

session.Store(doc, explicitIdValueString);

explicitIdValueStringGUID文字列にすることができます。この値は、データベース全体でドキュメントを識別するために使用され、タイプタグ名のプレフィックスは付きません。また、タグ名、またはID生成戦略を、どちらがであるかIDocumentStore.Conventionsなどの規則をオーバーライドすることにより、すべて一緒にカスタマイズすることもできます。FindTypeTagNameFunc<Type, string>

于 2012-10-02T00:00:30.903 に答える
2

主な問題は、RavenDBはクライアントでは数値/整数を処理できますが、サーバー側ではRavenDBが文字列IDを使用することです。

一般に、GUID/数値IDを使用することはお勧めしません。

于 2012-10-02T08:32:38.967 に答える
2

ユーザーがいて、これらのGUID識別子を生成するとします。

new User { Id = "users/" + Guid.NewGuid().ToString("N") }

正気を保つために、ドキュメントでは、不変として設定するためのキーを熱心に作成します。

public class User
{
    public User(Guid? guid = null)
    {
        IdPart = (guid ?? Guid.NewGuid()).ToString("N")
    }

    string IdPart { get; }
    string Id => $"Users/{IdPart}"

時々IdPartは実際にはキー全体です。「Users/abc」があるとします。ユーザーがプロジェクトを持っている場合。私は通常、次のようなドキュメントを作成します。

public class Project
{
    public User(Guid? userId = null)
    {
        UserId = "Users/" + (guid ?? Guid.NewGuid()).ToString("N");
        Id = $"{UserId}/project/"

    }

末尾のproject/これは、スラッシュの後にHiLo値を作成するようにレイヴンに通知することに注意してください。

この概念は、割り当てられた識別子、自然な識別子、およびシーケンス/ヒロ/アイデンティティキーの両方を簡単に混合すると同時に、ではなく読み取り可能な識別子を促進するために使用できます11何ですか?しかしUser/abc/project/1、私はそれが何であるかをあなたに言うことができます。abcによって作成された最初のプロジェクト

于 2016-08-09T14:05:47.950 に答える
-1
class MyIndex : AbstractIndexCreationTask<AB>
{
    public MyIndex()
    {
        Map = docs =>
            from d in docs
            select new
            {
                d.Id,
                d.BId,
                BName = string.Empty
            };

        TransformResults = (database, results) =>
            from r in results
            let b = database.Load<B>("bs/" + r.BId.ToString())
            select new
            {
                Id = Guid.Parse(r.Id.ToString().Split('/').Last()),
                r.BId,
                BName = b.Name
            };
    }
}
于 2014-02-06T10:24:29.530 に答える