Динамична монго проекция - проекция, която използва поле в документа, за да определи проекцията

Да кажем, че имам обект като този:

{default: 'x',
 types: {
  x:1,
  y:2,
  z:3
 }
}

Възможно ли е да изберете само types.x (т.е. проекция на {"types.x":1}), без да знаете, че x е по подразбиране предварително? Правенето на две заявки е очевидно възможно и не е това, което търся.


person B T    schedule 25.07.2014    source източник
comment
Кои са тези идиоти, които гласуват за затваряне на въпроси като този? Напълно ненужно. Хей идиот: когато гласуваш за затваряне на нещо, напиши коментар защо. Ако сте прав, тогава може би ОП ще избягва подобни въпроси в бъдеще. И ако грешите, всички виждаме колко тъпи са разсъжденията ви. Мисля, че е справедлива търговия.   -  person B T    schedule 25.07.2014
comment
всеки документ има ли собствена подразбиране? и въз основа на това искате да се проектира това поле? и всички възможни стойности по подразбиране известни ли са предварително?   -  person Asya Kamsky    schedule 26.07.2014
comment
като се замислите, бихте могли да направите това с рамка за агрегиране, ако вашата схема е различна (ако сте съхранили типовете като масив с {type:x, value:1} тип елементи.   -  person Asya Kamsky    schedule 26.07.2014
comment
Хм, интересна идея. Изненадан съм, че рамката за агрегиране не може да обработва ключове. Всеки документ има свои собствени настройки по подразбиране, да. А възможните стойности по подразбиране не са известни предварително.   -  person B T    schedule 26.07.2014


Отговори (1)


За съжаление това все още не е налично като част от рамката за обобщаване. Въпреки това, според този билет на JIRA, в момента той е „планиран от непланиран“. Единственият начин да направите това в момента е чрез използване на функцията map/reduce. Ако искате да продължите и да използвате това, това би означавало да направите нещо както следва:

  1. Картирайте всеки документ по _id и излъчете съответния ключ.
  2. Тъй като ще има само една стойност на ключ, функцията за намаляване няма да бъде извикана, но все пак трябва да инициализирате променливата, която използвате за функцията за намаляване. Можете да използвате празна функция или празен низ.
  3. Стартирайте map/reduce, запазвайки резултатите в колекция по ваш избор.

В обвивката mongo изглежда по следния начин:

var mapper = function() {
    var typeValue = this.types[this.default];
    emit(this._id, typeValue);
};
var reducer = "";

db.types.mapReduce(mapper, reducer, { out : "results" } );

Ако след това направите запитване към колекцията от резултати, ще получите нещо, както следва:

> db.results.find();
{ "_id" : ObjectId("53d21a270dcfb83c7dba8da9"), "value" : 1 }

Ако искате да знаете каква е стойността по подразбиране, можете да промените функцията mapper, за да върнете ключа също като стойност. Ще изглежда нещо подобно:

var mapper = function() {
    var typeValue = this.types[this.default],
        typeKey = "types." + this.default;

    emit(this._id, { key : typeKey, val : typeValue } );
};   

Когато се стартира, това ще доведе до резултати, които изглеждат както следва:

> db.results.find().pretty();
{
    "_id" : ObjectId("53d21a270dcfb83c7dba8da9"),
    "value" : {
        "key" : "types.x",
        "val" : 1
    }
}

Имайте предвид, че това вероятно е много по-сложно решение, отколкото бихте искали, но това е единственият начин да направите това с помощта на MongoDB, без да добавяте повече логика към вашето приложение.

person Juan Carlos Farah    schedule 25.07.2014
comment
Благодаря за отговора. Имате ли представа каква е ефективността на това в сравнение с двете обикновени заявки, които трябва да изпълня, за да има същия ефект? Или ефективността на изпълнение на една заявка, която избира всички типове? - person B T; 25.07.2014
comment
@BT, не бих ви препоръчал да използвате Map/Reduce за агрегиране в реално време. Някои от причините за това са обяснени тук. Ако не можете да промените схемата си, мисля, че най-добрият вариант би бил да изпълните двете редовни заявки. Освен това определено трябва да настоявате за внедряването на функцията в билета на JIRA, който копирах по-горе. С известен натиск от общността, той може да бъде внедрен в бъдещи версии на MongoDB. Надяваме се по-рано, отколкото по-късно. - person Juan Carlos Farah; 25.07.2014
comment
Благодаря за чудесната информация. Ще добавя моя коментар към списъка - person B T; 26.07.2014