2015-04-27 2 views
10

У меня возникла проблема с некоторыми данными, которые я храню в своем MongoDB (Примечание: я использую mongoose в качестве ODM). У меня есть две схемы:MongoDB - Query conundrum - Документ refs или subdocument

mongoose.model('Buyer',{ 
    credit: Number, 
}) 

и

mongoose.model('Item',{ 
    bid: Number, 
    location: { type: [Number], index: '2d' } 
}) 

Покупатель/Деталь будет иметь родителя/ребенка ассоциацию, с отношением один-ко-многим. Я знаю, что я могу настроить элементы для встраивания поддоков в документ покупателя или Я могу создать два отдельных документа с ссылками на идентификаторы объектов.

Проблемы я столкнулся в том, что мне нужно запросить товары где это ставка ниже, чем кредит покупателя но где расположение вблизи некоторых гео координаты.

Чтобы удовлетворить первые критерии, кажется, что я должен вставлять элементы в качестве поддомена, чтобы я мог сравнивать два числа. Но, чтобы сравнить местоположения с запросом geoNear, кажется, было бы лучше разделить документы, иначе я не смогу выполнить geoNear для каждого вложенного документа.

Есть ли способ, которым я могу выполнять обе задачи по этим данным? Если да, то каким образом я должен структурировать свои данные? Если нет, есть ли способ, которым я могу выполнить один запрос, а затем второй запрос результата из первого запроса?

Благодарим за помощь!

ответ

3

Существует еще один вариант (помимо внедрения и нормализации) для хранения иерархий в mongodb, который хранит их как tree structures. В этом случае вы будете хранить Покупателей и Элементы в отдельных документах, но в той же коллекции. Каждому элементу документа потребуется поле, указывающее на его документ покупателя (родителя), и родительское поле документа покупателя будет установлено равным нулю. Документы, которые я связал, чтобы объяснить несколько реализаций, которые вы могли бы выбрать.

2

Если ваши предметы хранятся в двух отдельных коллекциях, чем лучший вариант, вы будете писать свою собственную функцию и называть ее с помощью mongoose.connection.db.eval('some code...');. В таком случае вы можете выполнить свою расширенную логику на стороне сервера.

Вы можете написать что-то вроде этого:

var allNearItems = db.Items.find(
    { location: { 
     $near: { 
      $geometry: { 
       type: "Point" , 
       coordinates: [ <longitude> , <latitude> ] 
      }, 
      $maxDistance: 100 
     } 
    } 
}); 
var res = []; 
allNearItems.forEach(function(item){ 
    var buyer = db.Buyers.find({ id: item.buyerId })[0]; 
    if (!buyer) continue; 
    if (item.bid < buyer.credit) { 
     res.push(item.id); 
    } 
}); 
return res; 

После оценки (поместите его в mongoose.connection.db.eval("...") вызова), вы получите массив элементов id`s.

Используйте его с предостережениями. Если ваш массив allNearItems будет слишком большим или вы будете часто его запрашивать, вы можете столкнуться с проблемами производительности. Команда MongoDB фактически отказалась от прямого выполнения js-кода, но она по-прежнему доступна в текущей стабильной версии.

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