我想搜索属于用户的内容(靠近我)。我定义了以下索引,但我没有得到合并的结果集:
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为空。因此,似乎合并过程失败了。我只是不确定原因。
为什么结果显示经度而不是纬度属性也很奇怪。
在RAM中使用RavenDB Build 960。
我意识到我可以将位置反规范化为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
}
我似乎在学术上做错了。
答案 0 :(得分:0)
尝试:
答案 1 :(得分: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,
};
}
}