2013-03-05 13 views

risposta

1

In MongoDB ogni voce può contenere anche un numero diverso di campi, nonché nomi di campi diversi. Ecco perché un tale comando non è presente nelle API di Mongo: in MySQL puoi farlo perché ogni riga avrà lo stesso numero di colonne e lo stesso nome di colonna. In MongoDB non puoi fare questa ipotesi. Che cosa si può fare è quello di verificare se un campo è lì nel documento recuperato semplicemente:

if field_name in doc: 
    # Do stuff. 

dove field_name è il nome di "colonna" che si desidera verificare l'esistenza e la doc è la corrente doc puntato dal cursore. Ricorda che doc è un dict, quindi puoi trattarlo come se dovessi trattare qualsiasi altro dict in Python.

2

Prima domanda n., Poiché ciascun documento di una raccolta è indipendente; seconda domanda sì (tramite $exists):

# Get the count of docs that contain field 'fieldname' 
db.coll.find({'fieldname': {'$exists': 1}}).count() 
+0

Risposta breve e semplice. +1 per questo ... ma ancora in attesa di accettare qualsiasi risposta. Grazie Johnny – Workonphp

0

Ho affrontato lo stesso problema quando avevo a che fare con alcuni dati eterogenei di terze parti e ho risolto usando la mappa di ridurre l'intera collezione, ecco il codice js che ho usato nel caso in cui si può trovare utile:

function MapKeys() {  
var tmp,tmpEmpty,ChildObjTp,ChildIsAr; 
var levelCurrent=0; 
var record=this; 
function isArray(obj) {return typeof(obj)=='object'&&(obj instanceof Array);} 
//function emptyIf(obj){if (obj=='tojson') {return ' ';} else {return obj+' '}; } //@note date fields return .tojson so strip it 
function emptyIf(obj){if (typeof(this[obj])=='function') {return ' ';} else {return obj+' ';} } //@note date fields return .tojson so strip it 
//var toType = function(obj) {  // * http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 
// return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() 
// } 
function keysToArray(obj,propArr,levelMax, _level) { 
    /** example: r1=keysToArray(doc,[null,[] ],2,0) 
     _level is used for recursion and should always called with 0 
     if levelMax is negative returns maximum level 
     levelMax=0 means top level only 2 up to 2nd depth level etc. 
    */ 
     for (var key in obj) { 
      if (obj.hasOwnProperty(key)) { 
       if (obj[key] instanceof Object && ! (obj[key] instanceof Array)) 
        if (levelMax < 0 || _level+1 <= levelMax) { 
         {propArr[1].push(keysToArray(obj[key],[key,[] ],levelMax,_level+1));} 
        } 
        else {} //needed coz nested if ? 
       {propArr[1].push(key);} 
      } 
     } 
     return propArr; 
    } 
//---------------------------------------------------------------------------------------------- 
function arrayToStr(lst,prevKey,delimiter, inclKeys,levelMax,_level,_levelMaxFound) { 
    /** example: r2=arrayToStr(r1,'','|',true,2,0,0) 
     _level and _levelMaxFound is used for recursion and should always called with value 0 
     if levelMax is negative returns maximum level 
     levelMax=0 means top level only 2 up to 2nd depth level etc. 
    */ 
     var rt,i; 
     _levelMaxFound=Math.max(_level,_levelMaxFound); 
     if (prevKey !=='') {prevKey += '.';} 
     var rtStr =''; 
     if (lst[0])  {prevKey += lst[0]+'.';} 
     if (inclKeys) {rtStr += prevKey.slice(0,-1);} 
     for (var n in lst[1]) { 
      i=lst[1][n]; 
      if (typeof(i)=='string') { 
       rtStr += delimiter + prevKey + i; 
      } 
      else 
      { 
       if (levelMax < 0 || _level+1 <= levelMax) { 
        rt=arrayToStr(i,prevKey.slice(0,-1),delimiter, inclKeys,levelMax,_level+1,_levelMaxFound); 
        rtStr += delimiter + rt[0]; 
        _levelMaxFound=Math.max(rt[1],_levelMaxFound); 
       } 
       else {} 
      } 
     } 
     if (rtStr[0] == delimiter) {rtStr=rtStr.slice(1);} // Lstrip delimiters if any 
     return [rtStr,_levelMaxFound] 
    } 
//---------------------------------------------------------------------------------------------- 

var keysV=keysToArray(this,[null,[] ] ,parms.levelMax, 0); // we can't sort here coz array is nested 
keysV = arrayToStr(keysV,'',' ', parms.inclHeaderKeys,-1,0,0); 
var MaxDepth=keysV[1]; 
keysV=keysV[0].split(' '); // so we can sort 
keysV.sort();    // sort to make sure indentical records map to same id 
keysV=keysV.join(' '); 
emit ({type:'fieldsGrp',fields:keysV}, {cnt:1, percent:0.0,depth:MaxDepth,exampleIds:[this._id]});} 

function ReduceKeys (key, values) { 
//var total = {cnt:0,percent:0.0,exampleIds:[]} 
var total = {cnt:0, percent:0.0,depth:values[0].depth,exampleIds:[]} 
for(var i in values) { 
    total.cnt += values[i].cnt; 
    if (total.exampleIds.length < parms.Reduce_ExamplesMax){ 
     total.exampleIds = values[i].exampleIds.concat(total.exampleIds); 
     } 
    } 
return total;} 
1

dal momento che ogni documento è separato dall'altro non v'è alcun modo semplice per fare questo, però, se si vuole capire che cosa avete nella vostra collezione è possibile utilizzare Variety come descritto qui :

http://blog.mongodb.org/post/21923016898/meet-variety-a-schema-analyzer-for-mongodb

Fondamentalmente Mappa Riduce la raccolta per scoprire quali campi ci sono in essa.

Come ha detto @JohnnyHK, è possibile verificare l'esistenza di un campo utilizzando $exists: http://docs.mongodb.org/manual/reference/operator/exists/

1

Questo non è delle migliori pratiche, ma nella shell è possibile digitare

Object.keys (db.posts. findOne())

Nota: questo non mostra le chiavi interne nell'oggetto, è possibile utilizzare la mappa riduci per risolvere questo problema, ma se il proprio oggetto è semplice questo praticamente lo fa.

Problemi correlati