我如何与C#和MongoDB’和’多个$ elemMatch子句?
我使用10Gen认可的c#驱动程序用于mongoDB用于ac#应用程序和数据浏览我正在使用Mongovue。
以下是两个示例文档架构:
{ "_id": { "$oid": "4ded270ab29e220de8935c7b" }, "Relationships": [ { "RelationshipType": "Person", "Attributes": { "FirstName": "Travis", "LastName": "Stafford" } }, { "RelationshipType": "Student", "Attributes": { "GradMonth": "", "GradYear": "", "Institution": "Test1", } }, { "RelationshipType": "Staff", "Attributes": { "Department": "LIS", "OfficeNumber": "12", "Institution": "Test2", } } ] }, { "_id": { "$oid": "747ecc1dc1a79abf6f37fe8a" }, "Relationships": [ { "RelationshipType": "Person", "Attributes": { "FirstName": "John", "LastName": "Doe" } }, { "RelationshipType": "Staff", "Attributes": { "Department": "Dining", "OfficeNumber": "1", "Institution": "Test2", } } ] }
我需要一个查询来确保满足$ elemMatch标准,以便我可以匹配第一个文档,但不能匹配第二个文档。 以下查询适用于Mongovue。
{ 'Relationships': { $all: [ {$elemMatch: {'RelationshipType':'Student', 'Attributes.Institution': 'Test1'}}, {$elemMatch: {'RelationshipType':'Staff', 'Attributes.Institution': 'Test2'}} ]} }
如何在我的c#代码中执行相同的查询?
无法使用c#驱动程序构建上述查询(至少在版本1.0中)。
但是你可以构建另一个更清晰的查询,它将返回相同的结果:
{ "Relationships" : { "$elemMatch" : { "RelationshipType" : "Test", "Attributes.Institution" : { "$all" : ["Location1", "Location2"] } } } }
来自c#的相同查询:
Query.ElemMatch("Relationships", Query.And( Query.EQ("RelationshipType", "Test"), Query.All("Attributes.Institution", "Location1", "Location2")));
一个简单的解决方案是将多个IMongoQuery串在一起,然后将它们与Query.And结束:
List build = new List (); build.Add(Query.ElemMatch("Relationships", Query.EQ("RelationshipType", "Person"))); var searchQuery = String.Format("/.*{0}.*/", "sta"); build.Add(Query.ElemMatch("Relationships", Query.Or(Query.EQ("Attributes.FirstName", new BsonRegularExpression(searchQuery)), Query.EQ("Attributes.LastName", new BsonRegularExpression(searchQuery))))); var _main = Query.And(build.ToArray()); var DB = MongoDatabase.Create("UrlToMongoDB"); DB.GetCollection("nameOfCollectionInMongoDB").FindAs (_main).ToList();
`
我通过构造一组允许生成以下查询的类来解决当前问题:
{ 'Relationships': { $all: [ {$elemMatch: {'RelationshipType':'Student', 'Attributes.Institution': 'Test1'}}, {$elemMatch: {'RelationshipType':'Staff', 'Attributes.Institution': 'Test2'}} ] } }
以下是类定义:
class MongoQueryAll { public string Name { get; set; } public List QueryElements { get; set; } public MongoQueryAll(string name) { Name = name; QueryElements = new List (); } public override string ToString() { string qelems = ""; foreach (var qe in QueryElements) qelems = qelems + qe + ","; string query = String.Format(@"{{ ""{0}"" : {{ $all : [ {1} ] }} }}", this.Name, qelems); return query; } } class MongoQueryElement { public List QueryPredicates { get; set; } public MongoQueryElement() { QueryPredicates = new List (); } public override string ToString() { string predicates = ""; foreach (var qp in QueryPredicates) { predicates = predicates + qp.ToString() + ","; } return String.Format(@"{{ ""$elemMatch"" : {{ {0} }} }}", predicates); } } class MongoQueryPredicate { public string Name { get; set; } public object Value { get; set; } public MongoQueryPredicate(string name, object value) { Name = name; Value = value; } public override string ToString() { if (this.Value is int) return String.Format(@" ""{0}"" : {1} ", this.Name, this.Value); return String.Format(@" ""{0}"" : ""{1}"" ", this.Name, this.Value); } }
帮手搜索类:
public class IdentityAttributeSearch { public string Name { get; set; } public object Datum { get; set; } public string RelationshipType { get; set; } }
用法示例:
public List FindIdentities(List searchAttributes) { var server = MongoServer.Create("mongodb://localhost/"); var db = server.GetDatabase("IdentityManager"); var collection = db.GetCollection("Identities"); MongoQueryAll qAll = new MongoQueryAll("Relationships"); foreach (var search in searchAttributes) { MongoQueryElement qE = new MongoQueryElement(); qE.QueryPredicates.Add(new MongoQueryPredicate("RelationshipType", search.RelationshipType)); qE.QueryPredicates.Add(new MongoQueryPredicate("Attributes." + search.Name, search.Datum)); qAll.QueryElements.Add(qE); } BsonDocument doc = MongoDB.Bson.Serialization .BsonSerializer.Deserialize(qAll.ToString()); var identities = collection.Find(new QueryComplete(doc)).ToList(); return identities; }
我相信有一个更好的方法,但现在这个方法很有用,而且似乎足够灵活,可满足我的需求。 欢迎所有建议。
这可能是一个单独的问题,但由于某种原因,对于100,000个文档集,此搜索最多可能需要24秒。 我试过添加各种索引但无济于事; 在这方面的任何指针将是美妙的。