Reputation: 23972
Following the advice of this article I created a blob index on an array of objects in my documents. For example:
{
...
"itemID" : 37,
"MetaData" : [
{
"FileExtension" : "TXT"
},
{
"EmailSubject" : "GAS DESK HEAD MEETING"
},
{
"DocumentType" : "EMAIL"
},
{
"Date_BestEmailSent" : ISODate("2001-01-26T04:11:32.000Z")
},
{
"Date_ParentDate_BestDate" : ISODate("2001-01-26T04:11:32.000Z")
},
...
],
...
}
I'm now parsing a search tree in C# to build a query using the MongoDB C# driver:
IMongoQuery expression;
switch (leaf.Op)
{
case SearchOperation.Equals:
expression = Query.EQ(leaf.Field, leaf.Value);
break;
case SearchOperation.Contains:
expression = Query.Matches(leaf.Field, leaf.Field);
break;
...
}
if (_rootLevelFields.Contains(leaf.Field))
{
return expression;
}
return Query.ElemMatch("MetaData", expression);
In this case, if my search criteria was FileExtension EQ 'TXT'
It would run:
db.test.find({"MetaData": {$elemMatch: {"FileExtension":"TXT"}}})
This runs very slowly and the explain indicates it's scanning all records and not using my Index. If I manually run:
db.test.find({"MetaData": {"FileExtension":"TXT"}})
It uses the index and runs much faster. In this case it appears I don't want to use ElemMatch but the MongoDB Builder namespace doesn't seem to accommodate this type of query e.g.
Query.EQ("MetaData", expression);
is not syntactically correct. I've poured over the documentation and even the MongoDB driver source code but can't find how to do what I want. Am I missing something obvious?
Upvotes: 2
Views: 1433
Reputation: 12240
The EQ
method accepts only BSONValue
as a parameter, but you're trying to pass a IMongoQuery
instance.
In your second query you're basically searching this document in MetaData
array :
{"FileExtension":"TXT"}
You will need to create a new BsonDocument and pass it into your EQ
method:
Query.EQ("MetaData", new BsonDocument(leaf.Field, leaf.Value));
You can check the documentation for EQ method for more details.
Upvotes: 1