1

У меня есть следующий мангуст схема:

var dataSchema = new Schema({ 
    owner: { type: Schema.ObjectId, ref: 'User' }, 
    time : { type: Date, default: Date.now }, 
    eventCount:Number 
}); 

Для некоторого DataObjects eventCount определяется и положительное числом, для других DataObjects eventCount не определены. Я хочу разработать такой индекс, что запросы, подобные этому, как можно быстрее:

db.datacollection.find({owner: <some ID>, eventCount: {$exists:true}, time: {<some time range>}) 

Что такое лучший способ сделать это?

Вот лучшее решение, которое я мог думать, но мне было бы интересно знать, если кто имеет лучшее решение:

Добавить логическую переменную isEventCount в dataSchema. Настройте промежуточное программное обеспечение mongoose, чтобы вычислялось значение isEventCount, прежде чем сохранять объект в db со следующей логикой.

if(eventCount > 0) { 
    isEventCount = true; 
} else { 
    isEventCount = false; 
} 

затем строит индекс, как этот

db.datacollection.ensureIndex({user:1, isEventCount: 1, time:1}) 

и работает мой запрос, как этот

db.datacollection.find({owner: <some ID>, isEventCount: true, time: {<some time range>}) 

Есть несколько недостатков этого подхода. А именно:

  1. Я сохраняю избыточную информацию в базе данных.
  2. Для этого я должен написать дополнительный код промежуточного кода.
  3. Мне нужно изменить существующие записи в db.

Кто-нибудь знает о лучшем решении или библиотеке, которая может помочь с этим?

ответ

0

Вам не нужно проходить через все это, чтобы получить достойную производительность по этому запросу. Использование существующего запроса:

db.datacollection.find({owner: <some ID>, eventCount: {$exists:true}, time: {<some time range>} 

этот индекс:

db.datacollection.ensureIndex({user:1, eventCount: 1, time:1}) 

в большинстве случаев должно дать вам достаточно хорошую производительность. Очевидно, я не знаю размер или распределение существующего набора данных, но я думаю, для этого вам потребуется нечто довольно необычное для создания флага isEventCount.

Вообще говоря, прежде чем принимать какие-либо необычные меры проектирования схемы в MongoDB Я хотел бы сделать следующее:

1) Набор тестовых данных с разумными объемами 2) Попробуйте свои запросы, используя объяснения()

It даст вам довольно хорошее представление о том, насколько хорошо будет выполняться запрос и как/когда он использует индексы.

http://docs.mongodb.org/manual/reference/method/cursor.explain/#cursor.explain

+0

Я пробовал это. Это не работает.Представьте, что у меня есть следующие данные: {владелец: UserA, dataCount: 1, время: вчера) {владелец: UserA, dataCount: 1, time: lastYear} - Представьте, что существует 1000000 записей, подобных этому {владелец: UserA, dataCount: 2, time: вчера} Указанный выше индекс упорядочивает записи так, как я описал выше. И затем, если бы я должен был выполнить запрос: find ({owner: UserA, eventCount: {$ exists: true}, time: {c вчера)}) курсор должен будет сканировать все записи за последний год. –

+0

«не работает» означает, что запрос завершается с ошибкой? или вам не нравится производительность? вы можете удалить поле времени из индекса - как я уже сказал, я не знаю размер и распределение ваших данных, только вы это делаете. Дело в том, что вам не нужно вычисленное поле «isEventCount». В любом случае вам следует сопоставлять различные подходы, чтобы увидеть, что работает для вас - ни один подход схемы/индексации не будет работать для всех людей и всех случаев использования. –

+0

Не работает, так как мне не нравится производительность. Я хочу создать свои индексы таким образом, чтобы для этого конкретного запроса я хотел бы, чтобы «nscanned» равнялось количеству найденных объектов. С моей предложенной схемой, которая возможна, когда ваша схема невозможна. (Это относится к следующим наборам игрушек: '{" datacount ": 1," time ": ISODate (" 2013-06-10T15: 29: 32.603Z ")," exists ": true} {" datacount " : 2, «время»: ISODate («2014-06-10T15: 29: 32.603Z»), «существует»: true} {«datacount»: 1, «время»: ISODate («2014-06-10T15: 29: 32.603Z ")," exists ": true}') –