2012-02-21 1 views
1

Я знаю, что Multikeys позволяет эффективно находить объекты, у которых есть массив как поле, где в этом массиве присутствует определенное значение.В MongoDB вы можете индексировать поле для поиска объектов, которые не имеют значения в массиве?

Например, можно сохранить объект:

{ 
    "ar":["book","cat"] 
} 

И затем, при условии, что поле «ар» индексируется, вы могли бы сказать:

db.blah.find({"ar":"cat"}) 

И это будет эффективно найти выше объект.

Однако, было бы что-то вроде этой работы:

db.blah.find({"ar":{$not : "cat"}}) 

Здесь я хотел бы, чтобы найти все объекты, где «ар» массив делает не содержат «кошку». Будет ли этот запрос работать, и если он будет работать, будет ли он эффективным? (т. е. использовал бы индекс в поле «ar»?)

ответ

1

Если вы посмотрите на это MongoDB server issue, ответ будет «использовать индекс».

Однако при использовании оператора $not часто не очень эффективно использовать индекс. Если 'cat' появляется в 2% записей, вам все равно придется прочитать 98% данных. В этот момент вы можете просто просто прочитать весь набор данных по одной записи за раз.

+0

Идея состоит в том, что «кошка» появится во всех, кроме нескольких элементов. При этом проблема, о которой вы ссылаетесь, относится только к простому «не равному» в поле, она не относится к «не содержит» в массиве. – sanity

1

Оператор $ not не используется в том смысле, который вы подразумеваете, это мета-оператор, который используется, чтобы свести на нет только проверку другого оператора. Я думаю, что вы на самом деле означает использовать $ пе:

db.blah.find({ "ar" : { $ne : "cat"}}) 

Если вы сделаете это, и у вас есть индекс «ар», то потому, что это отрицательный матч вы будете иметь, чтобы сканировать только о всех документах в индексе для проверки каждого из них - это на самом деле менее эффективно, чем сканирование таблицы в одиночку, потому что вам нужно выполнить загрузку/сканирование индекса, а затем потянуть все данные, чтобы возвращать результаты тоже.

Если это достаточно важно и достаточно часто, чтобы избежать этого, то почему бы не добавить простое поле, которое является истинным/ложным (или 0/1 в моем примере), чтобы проверить существование «кошки», поле. Здесь я добавляю такое поле к существующему набору данных, я хотел бы предложить добавить его создания или модификации, чтобы добавить «кошку» в будущем, хотя - избежать пакетных операций, как правило, хорошая идея:

db.blah.update({ "ar" : "cat"}, { $set : {"cat_test" : 1 } }, true, true) 
db.blah.update({ "ar" : {$ne : "cat"}}, { $set : {"cat_test" : 0 } }, true, true) 
db.blah.ensureIndex({ "cat_test" : 1 }) 

сейчас вы можете просто запустить что-то вроде:

db.blah.find({ "cat_test" : 0 }) 

Это позволит эффективно использовать индекс. Независимо от того, стоит ли это, это будет зависеть от использования ваших данных и вашей модели, конечно

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