3

ユーザー(自分の近く)のものを探したい。次のインデックスを定義していますが、マージされた結果セットが得られません。

public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
    public class ThingsByLocationResult
    {
        public string ThingId { get; set; }
        public string UserId { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    public Things_ByLocation()
    {
        AddMap<Thing>(things => from t in things
                                select new
                                {
                                    ThingId = t.Id,
                                    UserId = (string)null,
                                    Latitude = 0,
                                    Longitude = 0,
                                    _ = (object)null,
                                });
        AddMap<User>(users => from u in users
                                select new
                                {
                                    ThingId = (string)null,
                                    UserId = u.Id,
                                    Latitude = u.Latitude,
                                    Longitude = u.Longitude,
                                    _ = SpatialIndex.Generate(u.Latitude, u.Longitude)
                                });

        Reduce = results => from result in results
                            group result by result.ThingId into g
                            let userId = g.Select(x => x.UserId).Where(t => !string.IsNullOrWhiteSpace(t)).FirstOrDefault()
                            let lat = g.Select(x => x.Latitude).Where(t => t != 0).FirstOrDefault()
                            let lng = g.Select(x => x.Longitude).Where(t => t != 0).FirstOrDefault()
                            select new
                            {
                                ThingId = g.Key,
                                UserId = userId,
                                Latitude = lat,
                                Longitude = lng,
                                _ = SpatialIndex.Generate(lat, lng)
                            };

        Store(x => x.ThingId, FieldStorage.Yes);
        Store(x => x.UserId, FieldStorage.Yes);
    }
}

結果は次のようになります。

{
  "ThingId": "Thing/Id26",
  "UserId": null,
  "Longitude": "0",
  "__spatialShape": "0.000000 0.000000"
}

私のモデル:

public class User
{
    public string Id { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public class Thing
{
    public string Id { get; set; }
    public double Name { get; set; }
    public double Description { get; set; }
    public string UserId { get; set; }
}

私が間違っていることについてのアイデアはありますか? グループをユーザーに切り替えると、ユーザー セクションが入力され、ThingId が null になります。したがって、マージ プロセスが失敗しているように見えます。理由はわかりません。

結果が経度を表示するのに緯度プロパティを表示しない理由についても、非常に奇妙です。

RAM で RavenDB Build 960 を使用する。

場所を Thing に非正規化できることはわかっていますが、それは、ユーザーの場所が変更された場合、潜在的に何百もの Thing を更新する必要があることを意味します。これは、これを行うための推奨される NoSql の方法ですか?

アップデート

Ayende の提案に基づいて、次のようになりました。

public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
    public class ThingsByLocationResult
    {
        public string ThingId { get; set; }
        public string UserId { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    public Things_ByLocation()
    {
        AddMap<Thing>(things => from t in things
                                select new
                                {
                                    ThingId = t.Id,
                                    UserId = (string)null,
                                    Latitude = 0,
                                    Longitude = 0
                                });
        AddMap<User>(users => from u in users
                                select new
                                {
                                    ThingId = (string)null,
                                    UserId = u.Id,
                                    Latitude = u.Latitude,
                                    Longitude = u.Longitude
                                });

        Reduce = results => from result in results
                            group result by result.ThingId into g
                            select new
                            {
                                ThingId = g.Key,
                                UserId = g.Select(x => x.UserId).Where(x => x != null).FirstOrDefault(),
                                Latitude = g.Select(x => x.Latitude).Where(t => t != 0).FirstOrDefault(),
                                Longitude = g.Select(x => x.Longitude).Where(t => t != 0).FirstOrDefault()
                            };

        Store(x => x.ThingId, FieldStorage.Yes);
        Store(x => x.UserId, FieldStorage.Yes);
    }
}

インデックス自体:

Map:
docs.Things
    .Select(t => new {ThingId = t.__document_id, UserId = (String)null, Latitude = 0, Longitude = 0})

Map:
docs.Users
    .Select(u => new {ThingId = (String)null, UserId = u.__document_id, Latitude = ((double)u.Latitude), Longitude = ((double)u.Longitude)})

Reduce:
results
    .GroupBy(result => result.ThingId)
    .Select(g => new {ThingId = g.Key, UserId = g
    .Select(x => x.UserId)
    .Where(x => x != null).FirstOrDefault(), Latitude = g
    .Select(x => ((double)x.Latitude))
    .Where(t => t != 0).FirstOrDefault(), Longitude = g
    .Select(x => ((double)x.Longitude))
    .Where(t => t != 0).FirstOrDefault()})

結果の投影は次のようになります。

{
  "ThingId": "Thing/Id26",
  "UserId": null,
  "Latitude": null,
  "Longitude": null
}

私はここで学問的に間違ったことをしているようです。

4

2 に答える 2

0

試行錯誤(そしてAyendeの提案)の過程を経て、私は次のようになりました。動作しますが、理由はわかりません。

データモデルを変更し、地理的位置データをThingに非正規化するのが最善であると思われます。

public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
    public class ThingsByLocationResult
    {
        public string Id { get; set; }
        public string UserId { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }
        public string SKU { get; set; }
        public string Name { get; set; }
    }

    public Things_ByLocation()
    {
        AddMap<Thing>(things => from t in things
                                select new
                                {
                                    Id = t.Id,
                                    UserId = t.UserId,
                                    Latitude = 0,
                                    Longitude = 0,
                                    Name = t.Name,
                                    SKU = t.SKU,
                                    _ = (object)null,
                                });
        AddMap<User>(users => from u in users
                                select new
                                {
                                    Id = (string)null,
                                    UserId = u.Id,
                                    Latitude = u.Latitude,
                                    Longitude = u.Longitude,
                                    Name = (string)null,
                                    SKU = (string)null,
                                    _ = (object)null, 
                                });

        Reduce = results => from result in results
                            group result by result.Id into g
                            let lat = g.Select(x => x.Latitude).Where(x => x != 0).FirstOrDefault()
                            let lng = g.Select(x => x.Longitude).Where(x => x != 0).FirstOrDefault()
                            let userId = g.Select(x => x.UserId).Where(x => x != null).FirstOrDefault()
                            let name = g.Select(x => x.Name).Where(x => x != null).FirstOrDefault()
                            let sku = g.Select(x => x.SKU).Where(x => x != null).FirstOrDefault()
                            select new
                            {
                                Id = g.Key,
                                UserId = userId,
                                Latitude = lat,
                                Longitude = lng,
                                Name = name,
                                SKU = sku,
                                _ = SpatialIndex.Generate(lat, lng)
                            };

        Store(x => x.Id, FieldStorage.Yes);
        Store(x => x.UserId, FieldStorage.Yes);

        TransformResults = (database, results) => from result in results
                                                    let user = database.Load<User>(result.UserId)
                                                    select new
                                                    {
                                                        Id = result.Id,
                                                        UserId = result.UserId,
                                                        Latitude = user.Latitude,
                                                        Longitude = user.Longitude,
                                                        Name = result.Name,
                                                        SKU = result.SKU,
                                                    };
    }
}
于 2012-07-16T10:00:57.677 に答える
0

試す:

  • マップから SpatialIndex.Generate を削除すると、reduce 上にのみ存在するはずです。
  • 縮小から SpatialIndex.Generate を削除し、必要に応じて緯度と経度を取得しない理由を確認します。
于 2012-07-13T07:56:55.563 に答える