ユーザー(自分の近く)のものを探したい。次のインデックスを定義していますが、マージされた結果セットが得られません。
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
}
私はここで学問的に間違ったことをしているようです。