2012-07-12 96 views
2

我想搜索属于用户(我附近)的内容。我有以下指标定义的,但我没有得到一个合并后的结果集:RavenDB中具有空间索引的多图索引失败

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。

我意识到我可以将位置变成正常的东西,但这意味着如果用户位置改变了,我将不得不更新潜在的数百个东西。这是首选的NoSql方式吗?

UPDATE

基于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

尝试:

  • 从地图上删除SpatialIndex.Generate,只应在减少。
  • 删除SpatialIndex.Generate从减少,只是看到为什么你不应该像你应该的纬度&经度。
+0

我试过了,我已经更新了我原来的问题。还是一个类似的问题。有什么建议么? – Junto 2012-07-16 08:34:04

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, 
                }; 
    } 
}