sub-object in sub-array in mongodb-C - mongodb

Here's the structure part of my collection :
{
...
list: [
{ id:'00A', name:'None 1' },
{ id:'00B', name:'None 2' },
],
...
}
Which method could you advise me to retrieve the list of values in the "id" and/or "name" field with C lib please ?

It seems you are asking for the equivalent of "db.collection.distinct" with the C driver. Is that correct? If so, you can issue distinct as a db command using the mongo_run_command function:
http://api.mongodb.org/c/current/api/mongo_8h.html#a155e3de9c71f02600482f10a5805d70d
Here is a piece of code you may find useful demonstrating the implementation:
mongo conn[1];
int status = mongo_client(conn, "127.0.0.1", 27017);
if (status != MONGO_OK)
return 1;
bson b[1]; // query bson
bson_init(b);
bson_append_string(b, "distinct", "foo");
bson_append_string(b, "key", "list.id"); // or list.name
bson_finish(b);
bson bres[1]; // result bson
status = mongo_run_command(conn, "test", b, bres);
if (status == MONGO_OK){
bson_iterator i[1], sub[1];
bson_type type;
const char* val;
bson_find(i, bres, "values");
bson_iterator_subiterator(i, sub);
while ((type = bson_iterator_next(sub))) {
if (type == BSON_STRING) {
val = bson_iterator_string(sub);
printf("Value: %s\n", val);
}
}
} else {
printf("error: %i\n", status);
}
The database is "foo" and the collection, containing documents similar to yours, is "test" in the above example. The query portion of the above is equivalent to:
db.runCommand({distinct:'foo', key:'list.id'})
Hope that helps.
Jake

Related

Mongoid throw 16052 exception

I want to use mongoid to implement the query funcation likes 'GROUP BY',but i caught an exception:
failed with error 16052: "exception: could not create cursor over th_test.messages for query : { sr_flag: /.*541260c5aee1a93f70000001.*/ } sort : { created_at: -1 }"
My code is here:
def messages
map = %Q{
function() {
emit(this.sr_flag, { count: 1 });
}
}
reduce = %Q{
function(key, values) {
var result = { count: 0 };
values.forEach(function(value) {
result.count += value.count;
});
return result;
}
}
result = Message.where(sr_flag: /.*#{self.id}.*/).map_reduce(map, reduce).out(inline: true).to_a
result
end
Can someone help me explain why? I had searched a blog.Does the mongoid set the created_at column as primary key?
I had fixed my problem.The reason was someone writed a default_scope for my Message model,but the column sorted on was not the key column of the map method.Just Using unscoped method to make program work.
result = Message.unscoped.where(sr_flag: /.*#{self.id}.*/).map_reduce(map, reduce).out(inline: true).to_a

Query key with value anywhere in object hierarchy in Mongo

In Mongo how can I find all documents that have a given key and value, regardless of where that key appears in the document's key/value hierarchy?
For example the input key roID and value 5 would match both:
{
roID: '5'
}
and
{
other: {
roID: '5'
}
}
There is no built in way to do this. You might have to scan each matched document recursively to try and locate that attribute. Not recommended. You might want to think about restructuring your data or perhaps manipulating it into a more unified format so that it will be easier (and faster) to query.
If your desired key appears in a fixed number of different locations, you could use the $or operator to scan all the possibilities.
Taking your sample documents as an example, your query would look something like this:
db.data.find( { "$or": [
{ "roID": 5 },
{ "other.roID": 5 },
{ "foo.bar.roID": 5 },
{ any other possbile locations of roID },
...
] } )
If the number of documents in collection is not so large, then it can be done by this:
db.system.js.save({_id:"keyValueExisted", value: function (key, value) {
function findme(obj) {
for (var x in obj) {
var v = obj[x];
if (x == key && v == value) {
return true;
} else if (v instanceof Object) {
if (findme(v)) return true;
}
}
return false;
}
return findme(this);
}});
var param = ['roID', '5'];
db.c.find({$where: "keyValueExisted.apply(this, " + tojsononeline(param) + ");"});

MongoDB getting size of cursor takes a long time if size is 0

I'm currently working on a project where I'm using keyword queries against a MongoDB. If I search for things that exists in the database everything works ok, but if I search for things that don't exist, or I have a typo in my query the appilcation basically crashes.
The query is as simple as this:
var query = Query.And(Query.Matches("text", searchText)
Where searchText is what's being written into the searchbox in the UI.
To check the size of the cursor I've tried implementing this:
if ( cursor.Size() == 0)
{
MessageBox.Show("Your search did not return a match. Please search for
something else.");
return database;
}
But the system takes 10-15 minutes to evaluate that the size is 0, compared to the 0.5 seconds if the size is 1 or more.
So do anyone have any suggestions? Either a better way of checking the size of the cursor or some kind of function that makes the method time out and tell the user that no match was found?
Thanks in advance.
Update:
As requested added the explain for something that should and something that shouldn't exist
db.docs.find( {text: "a"}).explain
function (verbose) {
/* verbose=true --> include allPlans, oldPlan fields */
var n = this.clone();
n._ensureSpecial();
n._query.$explain = true;
n._limit = Math.abs(n._limit) * -1;
var e = n.next();
function cleanup(obj){
if (typeof(obj) != 'object'){
return;
}
delete obj.allPlans;
delete obj.oldPlan;
if (typeof(obj.length) == 'number'){
for (var i=0; i < obj.length; i++){
cleanup(obj[i]);
}
}
if (obj.shards){
for (var key in obj.shards){
cleanup(obj.shards[key]);
}
}
if (obj.clauses){
cleanup(obj.clauses);
}
}
if (!verbose)
cleanup(e);
return e;
}
db.docs.find( {text: "fgrgfk"}).explain
function (verbose) {
/* verbose=true --> include allPlans, oldPlan fields */
var n = this.clone();
n._ensureSpecial();
n._query.$explain = true;
n._limit = Math.abs(n._limit) * -1;
var e = n.next();
function cleanup(obj){
if (typeof(obj) != 'object'){
return;
}
delete obj.allPlans;
delete obj.oldPlan;
if (typeof(obj.length) == 'number'){
for (var i=0; i < obj.length; i++){
cleanup(obj[i]);
}
}
if (obj.shards){
for (var key in obj.shards){
cleanup(obj.shards[key]);
}
}
if (obj.clauses){
cleanup(obj.clauses);
}
}
if (!verbose)
cleanup(e);
return e;
}
Update 2: Overview of indexes:
db.docs.getIndexes()
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "tweet_database.docs",
"name" : "_id_"
}

Use list in mongodb C driver

Here's the structure part of my collection :
{
...
likes: ['6a6ca923517f304900badd98','6a6ca923517f304900badd99','...'],
...
}
Which method could you advise me to retrieve the list of values in the "likes" field with C lib please ?
I don't have a working MongoDB C driver, but this should help get you started. Also, the docs should help you (here).
bson_iterator i[1], sub[i];
bson_type type;
const char * key;
const char * value;
// do query, get cursor
while(mongo_cursor_next(cursor) == MONGO_OK) {
// look for the "likes" field
if( bson_find( iterator, bson, "likes" )) {
// need to iterate through the elements of the array
bson_iterator_subiterator( iterator, sub );
// then iterate using "sub", until returns a BSON_EOO
while (BSON_EOO != bson_iterator_next( sub )) {
key = bson_iterator_key( sub );
// if it's a string...
value = bson_iterator_string( sub );
}
}
}

sub iterator object in mongodb C driver

Here's the structure part of my collection :
{
_id: {
id:"6a6ca923517f304900badd98",
target:"00badd6a6ca923517f304998e4df"
},
...
}
The use of :
if(bson_find(iterator, mongo_cursor_bson(cursor), "_id")){
bson_iterator_subiterator(iterator, sub);
id = (char*)bson_iterator_string(sub);
}
is "working" but in reality simply returns me the result of the first field of the array found...
How to recover precisely the value of the "id" or "target" field please ?
You can also use bson_iterator_more and bson_iterator_next upon the sub-iterator(It was still an iterator).
try this:
if(bson_find(iterator, mongo_cursor_bson(cursor), "_id"))
{
bson_iterator_subiterator(iterator, sub);
while(bson_iterator_more(sub))
{
if (bson_iterator_next(sub) != BSON_EOO)
{
printf("%s: %s\n", bson_iterator_key(sub), bson_iterator_string(sub));
}
}
}