Вернуть фактический тип поля в MongoDB - PullRequest
15 голосов
/ 09 июля 2010

В MongoDB, используя $type, можно отфильтровать поиск по тому, соответствует ли поле типу данных BSON (см. DOCS ).

Например,

db.posts.find({date2: {$type: 9}}, {date2: 1})

, который возвращает:

{ 
    "_id" : ObjectId("4c0ec11e8fd2e65c0b010000"), 
    "date2" : "Fri Jul 09 2010 08:25:26 GMT" 
}

Мне нужен запрос, который скажет мне, каков фактический тип поля для каждого поля в коллекции. Возможно ли это с MongoDB?

Ответы [ 4 ]

16 голосов
/ 26 июня 2016

Начиная с MongoDB 3.4, вы можете использовать оператор агрегирования $type для возврата типа поля.

db.posts.aggregate( 
    [ 
        { "$project": { "fieldType": {  "$type": "$date2"  } } } 
    ]
)

, что дает:

{ 
    "_id" : ObjectId("4c0ec11e8fd2e65c0b010000"), 
    "fieldType" : "string" 
}
16 голосов
/ 23 июня 2014

введите следующий запрос в оболочке монго

  typeof db.employee.findOne().first_name

Синтаксис

 typeof db.collection_name.findOne().field_name
7 голосов
/ 09 июля 2010

ОК, вот несколько связанных вопросов, которые могут помочь:

Получить все имена полей в коллекции, используя map-reduction.

Вот рекурсивная версия , в которой перечислены все возможные поля.

Надеюсь, это поможет вам начать. Однако я подозреваю, что с этим запросом у вас возникнут некоторые проблемы. Здесь есть две проблемы:

  1. Я не могу найти функцию "gettype" для JSON. Вы можете запросить по $type, но это не похоже на то, что вы действительно можете запустить функцию gettype для поля и получить обратно в тип BSON.
  2. Поле может содержать данные нескольких типов, поэтому вам потребуется план для их обработки. Даже если это не очевидно, Монго может хранить некоторые числа в виде целых чисел и других чисел без вашего ведома. На самом деле, с драйвером PHP это вполне возможно.

Таким образом, если вы предполагаете, что можете решить проблему № 1, тогда вы сможете решить проблему № 2, используя небольшое изменение «Получить все имена полей» .

Вероятно, это будет выглядеть примерно так:

"map" : function() { for (var key in this) { emit(key, [ typeof value[key] ]); } }
"reduce" : function(key, stuff) { return (key, add_to_set(stuff) ); }

Таким образом, в основном вы бы выдавали key и type of key value (в виде массива) в функции карты. Затем из функции Reduce вы добавляете уникальные записи для каждого типа.

В конце цикла у вас будут такие данные

{"_id":[255], "name" : [1,5,8], ... }

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

0 голосов
/ 29 мая 2015

Отметив, что a=5;a.constructor.toString() печатает function Number() { [native code] }, можно сделать что-то похожее на:

db.collection.mapReduce(function() { emit(this._id.constructor.toString().replace(/^function (\S+).+$/, "$1"), 1); }, function(k, v) { return Array.sum(v); }, { out: { inline: 1 } });

...