2014년 12월 12일 금요일

CDRIVER cannot use $or, $and in find queries

Can anyone that has used the C driver confirm that using $or and $and together or separately, do not work when using mongoc_collection_find()?

Whenever I use those operators, I get no results. Yet calling a bson_as_json() on the query itself, and copy and pasting that query into the shell works just fine.



Sorry to hear you are having trouble. Can you post the code for the query you are trying and a sample document that you expect to match?



It is either a problem with the structure of the query or the inputs. Here is an example where it works, maybe you can modify it for your own usage:



#include "mongoc.h"
#include "bson.h"
#include "stdio.h"
#include "stdlib.h"

int main(int argc, char* argv[]) {

    mongoc_client_t* client;
    mongoc_collection_t* collection;
    mongoc_cursor_t* cursor;
    bson_error_t error;
    bson_oid_t oid;
    bson_t *first_doc;
    bson_t *second_doc;
    bson_t *query_doc;

    client = mongoc_client_new("mongodb://localhost:27017");
    collection = mongoc_client_get_collection(client, "test", "wow");

    mongoc_collection_drop(collection, &error);

    first_doc = BCON_NEW("name", BCON_UTF8("tyler"));
    second_doc = BCON_NEW("name", BCON_UTF8("brock"));

    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, first_doc, NULL, &error);
    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, second_doc, NULL, &error);

    query_doc = BCON_NEW("$or",
        "[",
            "{", "name", BCON_UTF8("tyler"), "}",
            "{", "name", BCON_UTF8("brock"), "}",
        "]"
    );

    long count = mongoc_collection_count(collection, MONGOC_QUERY_NONE, query_doc, 0, 0, NULL, &error);
    printf("the count was: %ld\n", count);

    return EXIT_SUCCESS;
}



Tyler, thanks. I can get the query to work when I ONLY use the $or or $and operator as part of the query. 

But when I combine the expression with another field I get nothing back, for instance if you did something like below, do you still get results?

 query_doc = BCON_NEW("gender", BCON_UTF8("male"),"$or",

        "[",
            "{", "name", BCON_UTF8("tyler"), "}",
            "{", "name", BCON_UTF8("brock"), "}",
        "]"
    );



Sure, here is a more complete example using AND + OR:



#include "mongoc.h"
#include "bson.h"
#include "stdio.h"
#include "stdlib.h"

int main(int argc, char* argv[]) {

    mongoc_client_t* client;
    mongoc_collection_t* collection;
    bson_error_t error;
    bson_t *first_doc;
    bson_t *second_doc;
    bson_t *third_doc;
    bson_t *query_doc;

    client = mongoc_client_new("mongodb://localhost:27017");
    collection = mongoc_client_get_collection(client, "test", "wow");

    mongoc_collection_drop(collection, &error);

    first_doc = BCON_NEW("name", BCON_UTF8("tyler"), "gender", BCON_UTF8("male"));
    second_doc = BCON_NEW("name", BCON_UTF8("brock"), "gender", BCON_UTF8("male"));
    third_doc = BCON_NEW("name", BCON_UTF8("brock"), "gender", BCON_UTF8("female"));

    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, first_doc, NULL, &error);
    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, second_doc, NULL, &error);
    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, third_doc, NULL, &error);

    query_doc = BCON_NEW(
        "gender", BCON_UTF8("male"),
        "$or", "[",
            "{", "name", BCON_UTF8("tyler"), "}",
            "{", "name", BCON_UTF8("brock"), "}",
        "]"
    );

    long count = mongoc_collection_count(collection, MONGOC_QUERY_NONE, query_doc, 0, 0, NULL, &error);
    printf("the count was: %ld\n", count);

    bson_destroy(first_doc);
    bson_destroy(second_doc);
    bson_destroy(third_doc);

    mongoc_collection_destroy(collection);
    mongoc_client_destroy(client);

    return EXIT_SUCCESS;
}



You can compile the example with:

gcc bcon_test.c $(pkg-config --cflags --libs libmongoc-1.0)

And the expected output count is 2.

Let me know if that makes sense and works for you.



It makes sense and it runs fine, but my problem was with find() not count(). So, I've edited that program and run it. I've added a mongoc_collection_find using the same query, shouldn't that print results then...?

#include <mongoc.h>

#include <bson.h>

#include "stdio.h"

#include "stdlib.h"


int main(int argc, char* argv[]) {
  

    mongoc_client_t* client;

    mongoc_collection_t* collection;

    mongoc_cursor_t *cursor;

    bson_error_t error;

    bson_t *first_doc;

    bson_t *second_doc;

    bson_t *third_doc;

    bson_t *query_doc;

    const bson_t *doc;

    char *str;

   
    client = mongoc_client_new("mongodb://localhost:27017");

    collection = mongoc_client_get_collection(client, "test", "wow");
   

    mongoc_collection_drop(collection, &error);
 

    first_doc = BCON_NEW("name", BCON_UTF8("tyler"), "gender",BCON_UTF8("male"));

    second_doc = BCON_NEW("name", BCON_UTF8("brock"), "gender",BCON_UTF8("male"));

    third_doc = BCON_NEW("name", BCON_UTF8("brock"), "gender",BCON_UTF8("female"));
  

    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, first_doc,NULL, &error);

    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, second_doc,NULL, &error);

    mongoc_collection_insert(collection, MONGOC_INSERT_NONE, third_doc,NULL, &error);

   
    query_doc = BCON_NEW(

                         "gender", BCON_UTF8("male"),

                         "$or", "[",

                         "{", "name", BCON_UTF8("tyler"), "}",

                         "{", "name", BCON_UTF8("brock"), "}",

                         "]"

                         );
   

    long count = mongoc_collection_count(collection, MONGOC_QUERY_NONE,query_doc, 0, 0, NULL, &error);

    printf("the count was: %ld\n", count);
   

    cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0,0, query_doc, NULL, NULL);
   

    while(mongoc_cursor_next(cursor, &doc)){

        str = bson_as_json(doc, NULL);

        printf("result: %s\n",str);

        bson_free(str);

    }
  

    bson_destroy(first_doc);

    bson_destroy(second_doc);

    bson_destroy(third_doc);
   

    mongoc_collection_destroy(collection);

    mongoc_client_destroy(client);

    mongoc_cursor_destroy(cursor);

    return EXIT_SUCCESS;

}


I'm using the latest rc on OS X btw, hopefully that doesn't change anything, but I compiled whatever the latest tarball is from github.



You are correct, if you look at the cursor error by calling mongoc_cursor_error(...) you will see something along the lines of:

"Cannot mix top-level query with dollar keys such as $orderby. Use {$query: {},...} instead."

This is because when you have $ in the query it you need to nest it in a $query field like so:

    query_doc = BCON_NEW(
        "$query", "{",

            "gender", BCON_UTF8("male"),
            "$or", "[",
                "{", "name", BCON_UTF8("tyler"), "}",
                "{", "name", BCON_UTF8("brock"), "}",

            "]",
        "}"
    );



Interesting, I'll give that a shot.



Ok, let me know how that works out.


댓글 없음:

댓글 쓰기