0

This is the first of 7 test/example documents, in collection "SoManySins."

{
  "_id" : ObjectId("51671bb6a6a02d7812000018"),
  "Treats" : "Sin1 = Gluttony",
  "Sin1" : "Gluttony",
  "Favourited" : "YES",
  "RecentActivity" : "YES",
  "GoAgain?" : "YeaSure."
}

I would like to be able to query to retrieve any info in any position, just by referring to the position. The following document,

{
   "_id" : ObjectId("51671bb6a6a02d7812000018"),
   "Sin1" : "Gluttony",
   "?????????" : "??????",
   "RecentActivity" : "YES",
   "GoAgain?" : "YeaSure."
} 

One could retrieve whatever might be in the 3rd key~value pair. Why should one have to know ahead of time what the data is, in the key? If one has the same structure for the collection, who needs to know? This way, you can get double the efficiency? Like having a whole lot of mailboxes, and your app's users supply the key and the value; your app just queries the dbs' documents' arrays' positions. Clara? finally? I hope?

MountainMan
  • 733
  • 1
  • 9
  • 20
  • Your description suggested nested arrays but your sample document does not have this structure. What exactly are you expecting as output for the query? – Stennie Apr 10 '13 at 06:05
  • The [`$slice` projection](http://docs.mongodb.org/manual/reference/projection/slice/) you are trying to use in your shell examples only works with array fields and you must specify the field name (your syntax isn't correct). If you had an array `Sins` you could use `$slice` to select a subset of array elements but this seems like an odd use case. Can you include an example of the output format you want as well? – Stennie Apr 10 '13 at 06:39
  • I'm still unclear what your query and output would look like. If you just want to get all fields, don't specify a list in the projection eg: `db.SoManySins.find()`. If you had an array and wanted to reference by position (and not name) you can use the numeric array index instead of the field name, but the array order may not be consistent across documents. Are you actually trying to get the *names* of the fields and not the values? – Stennie Apr 10 '13 at 11:42
  • You can certainly return partial documents with a projection or aggregation query based on values for known keys (see: [MongoDB extract only the selected item in array](http://stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array)). You can also use [`$slice`](http://docs.mongodb.org/manual/reference/projection/slice/) to take a subset of an array. If you could include an example of how you would like to query (and what you would output you like to receive) that would really help clarify the question you're trying to ask :). – Stennie Apr 11 '13 at 21:01
  • @Stennie Reworked the question rather extensively, sure. – MountainMan Apr 12 '13 at 00:01

2 Answers2

0

The sample document you've provided is not saved as an array in BSON:

{
    "_id" : ObjectId("51671bb6a6a02d7812000018"),
    "Sin1" : "Gluttony",
    "?????????" : "??????",
    "RecentActivity" : "YES",
    "GoAgain?" : "YeaSure."
}

Depending on the MongoDB driver you are using, the fields here are typically represented in your application code as an associative array or hash. These data structures are not order-preserving so you cannot assume that the 3rd field in a given document will correspond to the same field in another document (or even that the same field ordering will be consistent on multiple fetches). You need to reference the field by name.

If you instead use an array for your fields, you can refer by position or select a subset of the array using the $slice projection.

Example document with an array of fields:

{
    "_id" : ObjectId("51671bb6a6a02d7812000018"),
    "fields": [
        { "Sin1" : "Gluttony" },
        { "?????????" : "??????" },
        { "RecentActivity" : "YES" },
        { "GoAgain?" : "YeaSure." }
    ]
}

.. and query to find the second element of the fields array (a $slice with skip 1, limit 1):

db.SoManySins.find({}, { fields: { $slice: [1,1]} })
{
    "_id" : ObjectId("51671bb6a6a02d7812000018"),
    "fields" : [
        {
            "?????????" : "??????"
        }
    ]
}
Stennie
  • 57,971
  • 14
  • 135
  • 165
  • Great stuff, now working after I restructured some data; now to attempt finding the php equivalent in the archieved docs. – MountainMan Apr 15 '13 at 19:48
0

This is one way to Query and get back data when you may not know what the data is, but you know the structure of the data: examples in Mongo Shell, and in PHP

// the basics, setup:

 $dbhost = 'localhost'; $dbname = 'test';
 $m = new Mongo("mongodb://$dbhost");
 $db = $m->$dbname;
 $CursorFerWrites = $db->NEWthang; 

// defining a set of data, creating a document with PHP:

 $TheFieldGenerator = array( 'FieldxExp' => array(
 array('Doc1 K1'=>'Val A1','Doc1 K2'=>'ValA2','Doc1 K3'=>'Val A3'),
 array('Doc2 K1'=>'V1','Doc2 K2'=>'V2','Doc2 K3'=>'V3' ) ) ) ; 

// then write it to MongoDB:

 $CursorFerWrites->save($TheFieldGenerator); 

NOTE : In the Shell : This produces the same Document:

 > db.NEWthang.insert({"FieldxExp" : [
       {"Doc1 K1":"Val A1","Doc1 K2":"Val A2","Doc1 K3":"Val A3"},
       {"Doc2 K1":"V1", "Doc2 K2":"V2","Doc2 K3":"V3"}
                                                                      ]
                                           }) 

#


Now, some mongodb Shell syntax:

 > db.NEWthang.find().pretty()
    {
         "_id" : ObjectId("516c4053baa133464d36e836"),
         "FieldxExp" : [
            {
                    "Doc1 K1" : "Val A1",
                    "Doc1 K2" : "Val A2",
                    "Doc1 K3" : "Val A3"
            },
            {
                    "Doc2 K1" : "V1",
                    "Doc2 K2" : "V2",
                    "Doc2 K3" : "V3"
            }
    ]
 }
 > db.NEWthang.find({}, { "FieldxExp" : { $slice: [1,1]} } ).pretty()
 {
    "_id" : ObjectId("516c4053baa133464d36e836"),
    "FieldxExp" : [
            {
                    "Doc2 K1" : "V1",
                    "Doc2 K2" : "V2",
                    "Doc2 K3" : "V3"
            }
    ]
 }

 > db.NEWthang.find({}, { "FieldxExp" : { $slice: [0,1]} } ).pretty()
   {
    "_id" : ObjectId("516c4053baa133464d36e836"),
    "FieldxExp" : [
            {
                    "Doc1 K1" : "Val A1",
                    "Doc1 K2" : "Val A2",
                    "Doc1 K3" : "Val A3"
            }
      ]
 } 

Finally, how about write the Query in some PHP ::

// these will be for building the MongoCursor:

 $myEmptyArray = array();
 $TheProjectionCriteria = array('FieldxExp'=> array('$slice' => array(1,1))); 

// which gets set up here:

 $CursorNEWthang1 = new MongoCollection($db, 'NEWthang'); 

// and now ready to make the Query/read:

 $ReadomgomgPls=$CursorNEWthang1->find($myEmptyArray,$TheProjectionCriteria); 

and the second document will be printed out:

 foreach ($ReadomgomgPls as $somekey=>$AxMongoDBxDocFromCollection) {
var_dump($AxMongoDBxDocFromCollection);echo '<br />';
 }

Hope this is helpful for a few folks.

MountainMan
  • 733
  • 1
  • 9
  • 20