[CDRIVER-701] Client-side array and document matching Created: 09/Jun/15  Updated: 24/Apr/17  Resolved: 21/Sep/15

Status: Closed
Project: C Driver
Component/s: libmongoc
Affects Version/s: 1.1.6
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Dan Bauman Assignee: A. Jesse Jiryu Davis
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

RHEL6


Issue Links:
Related
is related to CDRIVER-954 Deprecate mongoc_matcher_t Closed

 Description   

Followon to CDRIVER-641

Matcher_t does not seem to work for values as arrays. The docs may indicate it should (https://github.com/mongodb/mongo-c-driver/blob/58f9962777150d013101581a1e974620acf57696/doc/matcher.page#L11)?

I'm running the latest (1.1.6) release

Generate a doc/subdoc with string value

>>> doc_str = {"base":{"subdoc":"value"}}

Generate a doc/subdoc with string inside array

>>> doc_arr = {"base":{"subdoc":["value"]}}

Generate a valid mongo spec that should match on both documents

>>> spec = {"base.subdoc":{"$in":["value", "some_other_value"]}}

Generate the matcher

>>> matcher = bc.generate_matcher(spec)

Compare correctly against the first document

>>> bc.match(matcher, doc_str)

True

Compares incorrectly against the second document.

>>> bc.match(matcher, doc_arr)

False



 Comments   
Comment by A. Jesse Jiryu Davis [ 22/Oct/15 ]

I've reconsidered, and I still don't think we should continue developing mongoc_matcher_t. bauman I really appreciate your effort to extend this feature; I think you have two clear options:

1. Copy mongoc_matcher_t and related code into your own repository and continue developing it there to support additional features.
2. Port your client-side matcher library from mongoc_matcher_t to wrap the server's actual query engine instead.

The latter is more promising since you will have the server's full query power, and you'll be able to easily track enhancements to the query engine as they're released in the future.

In the server's C++ matcher API, you call MatchExpressionParser::parse(const BSONObj& obj).getValue() to get a MatchExpression. MatchExpression::matchesBSON will match the query against a given document.

A colleague on the server team says,

It should be possible to link the $BUILD_DIR/mongo/db/matcher/expressions library without the rest of the server codebase. This is exacly what the matcher unit tests do, for example.

https://github.com/mongodb/mongo/blob/master/src/mongo/db/matcher/SConscript#L27 is where we declare the expressions library

https://github.com/mongodb/mongo/blob/master/src/mongo/db/matcher/SConscript#L49-L60 is a unit test that depends on it

Comment by A. Jesse Jiryu Davis [ 16/Jun/15 ]

Neat! I like your search package. If you're willing to make the effort I'd look forward to a patch from you.

Comment by Dan Bauman [ 16/Jun/15 ]

understand that it is never intended to be anywhere close to full mongodb. I certainly don't want it to be anywhere close.

It's functional as-is, but I had to write my own unwind function to generate discrete documents when it ran into a list. I don't mind the slowdown, but I'd like let libbson do the work where it makes sense.

I'm still trying to wrap my head around the design pattern to understand what I'm looking at. I'm not opposed to building a few cases and providing unit tests for the ones I need. Going to take a while.

simple ctypes wrapper for what I need. Nothing special.
https://github.com/bauman/bsonsearch

Comment by A. Jesse Jiryu Davis [ 16/Jun/15 ]

I'm cautious about adding features to the matcher, since that is an unending task and a doomed one. The driver will never behave the same as any particular MongoDB version. I know I just added some features myself, but I only did it because the driver needed those features for self-testing.

That said, if you'd like to offer a very well-tested pull request I'd consider it for 1.2 or 1.3.

Also, what shell are you using to test it? Is that a Python wrapper around the matcher?

Comment by Dan Bauman [ 09/Jun/15 ]

Doesn't look like it is the $in operator

>>> spec =

{"base.subdoc":"value"}

>>> matcher = bc.generate_matcher(spec)

>>> bc.match(matcher, doc_str)

True

>>> bc.match(matcher, doc_arr)

False

I guess it needs to unroll the right side in
_mongoc_matcher_iter_eq_match

https://github.com/mongodb/mongo-c-driver/blob/480de4b10511c9ad7b406a02979285b9e8cc8be7/src/mongoc/mongoc-matcher-op.c#L416

Something like...

mongoc-matcher-op.c

case _TYPE_CODE(BSON_TYPE_UTF8, BSON_TYPE_ARRAY):
      {
         bson_iter_t left_array;
         bson_iter_t right_array;
         bson_iter_recurse (iter, &right_array);
         //still thinking
         while (true) {
            bool right_has_next = bson_iter_next (&right_array);
            //still thinking
         }
      }

Generated at Wed Feb 07 21:10:22 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.