2013-11-23 3 views
1

У меня есть коллекция около 200K документов, как это:MongoDB найти сравнение элементов массива

db.place.find()[0] 
{ 
    "_id" : ObjectId("5290de1111afb260363aa4a1"), 
    "name" : "place X", 
    "center" : [x, y] 
} 

Теперь I`m пытается запросить те места, где центр Y больше, то X, и имеющей следующей проблема :

> db.place.find({'center.0':{'$gt':center.1}}).count() 
Sat Nov 23 14:42:01.556 JavaScript execution failed: SyntaxError: Unexpected number 

Любые подсказки? Заранее спасибо

+2

должно быть: 'db.place.find ({'cen ter.0 ': {' $ gt ':' center.1 '}}). count() 'Обратите внимание на цитаты вокруг центра.1 – idbentley

+0

Я пробовал этот запрос, но кажется, что он не работает. Я использую версию 2.4.7. Я отвел ответ вместо $ where вместо оператора. –

+0

вы не можете ссылаться на содержимое документа с правой стороны от того, где (то есть {a: 1} в порядке, {a: b}, где b - другое поле, не в порядке. Если вам нужно сравнить x и y вы может считать, что схема не подходит для вашего случая использования - вам нужно хранить x и y, как это? –

ответ

3

Поскольку каждый раз, когда у вас есть точный формат поля (круг представляет собой массив из двух элементов), вы можете преобразовать его в структуру агрегации в два поля, а затем сравнить их в проекции и сопоставить, чтобы вернуть только элементы удовлетворяющий вашему требованию второго элемента массива, который больше, чем первый элемент массива.

db.place.aggregate([ 
     { $unwind : "$center" }, 
     { $group : { _id : "$_id", 
        centerX : {$first:"$center"}, 
        centerY : {$last:"$center"} 
     } }, 
     { $project : { YgtX : { $gt : [ "$centerY", "$centerX" ] } } }, 
     { $match : { YgtX : true } } 
]); 

Теперь, если ваш массив был произвольной парой числовых значений, вы можете использовать приведенное выше.

Вы сказали в комментариях, что ваша пара представляет координаты (lat, long) - имейте в виду, что в координатных парах MongoDB всегда stored as long, lat - если ваши фактические значения x, y были координатами на плоской (в отличие от сферической) место, можно найти все документы, которые имели Y координат больше, чем координата X с помощью одного геопространственной запроса:

db.place.find({ center : { $geoWithin : { $geometry : { 
        type:"Polygon", 
        coordinates:[[[50,50],[-50,50],[-50,-50],[50,50]]] 
} } } }); 

Этот запрос предполагает, что ваша система координат идет от -50 до 50 по X и Y, и он находит все точки в треугольнике, которые представляют все координаты, имеющие Y> = X.

+3

Прохладный !!! Очень неожиданное решение :)) –

2

Кажется, что вам нужно использовать $where.

db.place.find({$where: function() {return this.center[0] > this.center[1]}}) 

Например, есть 3 документов в коллекции:

{ "_id" : ObjectId("52910457c7d99f10949e5a85"), "name" : "place X", "center" : [ 2, 3 ] } 
{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3, 2 ] } 
{ "_id" : ObjectId("5291046ac7d99f10949e5a87"), "name" : "place Y", "center" : [ 8, 9 ] } 

Результат $, где команда будет:

{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3, 2 ] } 
+1

Здравствуйте, Виктория, благодарю вас за ответ. Как сказал Сальвадор Дали, это не практическое решение ... Будет продолжать искать быстрый способ. –

1

Вы не можете сделать запрос, который вы хотите в простой способ в mongo, потому что mongo не поддерживает поиск или обновление на основе элемента в коллекции. Поэтому даже такой простой документ, как {a : 1, b : 1}, и найти документ, где a = b невозможно без предложения $where.

Решение, предлагаемое idbentley db.place.find({'center.0':{'$gt':'center.1'}}), также не будет работать (также не будет генерировать ошибку), потому что таким образом вы сравните center.0 с строкой 'center.1'. Поэтому правильным решением является решение Виктории Малой (но она забыла положить .count() в конце).

Одна вещь, которую я хотел бы предложить. Все, что там, где очень медленно. Поэтому, если вы собираетесь делать этот запрос более одного раза, подумайте о создании дополнительного поля, которое сохранит этот предварительно вычисленный результат (вы можете сделать это аналогичным образом с ответом this).

Смежные вопросы