2014-04-08 43 views
0

我正在搜索一系列商店。商店有一个嵌入式地点集合。我的目标是返回在地理位置附近有商店的商店集合,并且仅返回那些位置在之内的商店在Mongoose附近使用elemMatch

我可以成功地限制查询只返回商店使用“近”


Store 
    .where('isActive').equals(true) 
    .where('outlets.location') 
    .near({ center: [153.027117, -27.468515], maxDistance: 1000/6378137, spherical: true }) 
    .where('outlets.isActive').equals(true) 
    .where('products.productType').equals('53433f1f3e02e39addde1954') 
    .where('products.isActive').equals(true) 
    .select('name outlets') 
    .select({'products': {$elemMatch: {'isActive': true, 'productType': '53433f1f3e02e39addde1954'}}}) 
    .select('name outlets') 
    .execQ() 
    .then(function (results) { 
    console.log(results); 
    }) 
    .fail(function (err) { 
    console.log(err); 
    }) 
    .done(); 

具有在特定位置的出口我的问题是,这家店的文档返回所有的网点,而不仅仅是出口与地理位置相匹配。我尝试过使用elemMatch,像我对产品做过的那样;

。选择({ '网点':{$ elemMatch:{ '位置':{邻近:{中心:[153.027117,-27.468515],maxDistance:六百三十七万八千一百三十七分之一万,球形:真}}}}} )

但是它返回一个空数组。在elemMatch子句中可以使用near操作符吗?我做错了吗?是否有更高效/更快/更好的方式来实现目标?

+0

答案中有些东西不清楚吗?我认为情况已经非常明确地解释了。 –

回答

1

我明白你在这里想要做什么,但在这种设计中似乎有一些缺陷。虽然不完全是你的文档结构我看你正在尝试做这样的事情:

{ 
    "_id" : ObjectId("5344badd519563414f23fdf8"), 
    "store" : "Mine", 
    "outlets" : [ 
      { 
        "name" : "somewhere", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            150.975131, 
            -33.8440366 
          ] 
        } 
      }, 
      { 
        "name" : "else", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            151.3651524, 
            -33.8389783 
          ] 
        } 
      } 
    ] 
} 
{ 
    "_id" : ObjectId("5344be6f519563414f23fdf9"), 
    "store" : "Another", 
    "outlets" : [ 
      { 
        "name" : "else", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            151.3651524, 
            -33.8389783 
          ] 
        } 
      }, 
      { 
        "name" : "somewhere", 
        "loc" : { 
          "type" : "Point", 
          "coordinates" : [ 
            150.975131, 
            -33.8440366 
          ] 
        } 
      } 
    ] 
} 

所以基本上你似乎试图窝在阵列内的出口位置在顶层文件。

我在这里指的是一个缺陷是,通过设计,任何类型的“近”基于查询将返回多于1个结果。当你看到目的时,这似乎是合乎逻辑的。你当然可以通过“maxDistance”来修改这个结果,但通常它会大于1.

所以唯一的办法就是将光标返回的结果作为一个“最近”的响应。还要注意的是,对于某些操作,这些结果不一定是“排序”的“最近的响应优先”。

现在,因为这些结果实际上包含在文档数组中,请记住.find()本身并不实际“过滤”当然文档将包含所有的数组内容

如果您尝试使用位置$运算符“投影”,那么问题会回落到原始点,因为没有单个的实际值匹配,所以不可能为匹配元素返回一个“索引”值,如果你确实尝试了这个,你总会得到默认索引值0,所以只返回第一个元素。

如果你认为你可以逃跑来聚合,并试图实际“解规范”数组条目,那么你会不走运,因为由于需要使用第一个阶段的索引任何聚合管道语句。

因此,总结这样的嵌入式条目不适合这种设计,你需要在这些商店位置上进行地理空间匹配。该位置是在一个单独的收集更好:

{ 
    "_id" : ObjectId("5344bec7519563414f23fdfa"), 
    "store": "Mine" 
    "name" : "else", 
    "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
        151.3651524, 
        -33.8389783 
      ] 
    } 
} 
{ 
    "_id" : ObjectId("5344bed5519563414f23fdfb"), 
    "store": "Mine" 
    "name" : "somewhere", 
    "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
        150.975131, 
        -33.8440366 
      ] 
    } 
} 

因此,这将让你“限制”结果到“最近”的比赛被限制设置为1,您还可以包括任何必要的值,如在您的过滤中使用的“商店”。如果你需要的话,除了需要过滤的内容之外,还可以包含其他信息,或者只需将ObjectId值放入原始对象的数组中,或者甚至可以为两个集合重复。

但是,由于这些查询的本质不仅仅是返回1个匹配,那么您将无法使这个工作在嵌入式文档上。因此,您的解决方案需要对整个架构进行一些更改。

+0

谢谢尼尔!这是一个很好的问题总结。展望未来,我会将网点转移到他们自己的文档中。 – Robert