为不同类型的嵌套文档制作动态构建器过滤器 - MongoDB C#驱动程序
我有一个名为some_collection
的集合。为some_collection
的模式是这样的:(该模式通过C#DTO决定)为不同类型的嵌套文档制作动态构建器过滤器 - MongoDB C#驱动程序
{
_id: ObjectId(.....),
firstName: "fName",
lastName: "lName",
someType: 4,
innerObject: {
// see below
}
}
在我的C#代码,innerObject是一个抽象类,并有多个孩子的类。这些子类具有不同的属性,因此MongoDB集合中的文档不完全相同。他们所属的子类的类型由个人some_collection
文档中的someType
字段划定。所以,有2种不同类型的嵌套文档的audit_collection
的2个文件的例子:
{
_id: ObjectId('first'),
firstName: "Jane",
lastName: "Smith",
someType: 0,
innerObject: {
prop1: "foo",
prop2: "bar",
aCollectionOfStrings: ["a", "b", "c"] // this is what I wanna search
}
},
{
_id: ObjectId('second'),
firstName: "John",
lastName: "Doe",
someType: 3,
innerObject: {
prop1: "baz",
prop2: "foobarbaz",
aCollectionOfObjects: [
{
myProp: "hello", // this is what I want to search
irrelevantProp: "blah"
},
{
myProp: "hello5", // this is what I want to search
irrelevantProp: "blah"
},
{
myProp: "hello1", // this is what I want to search
irrelevantProp: "blah"
}
]
}
}
的应用案例这个问题,我想搜索用户提供的字符串,这样就可以在存在firstname
和lastname
属性(它位于文档的顶层,所有文档都很容易分享),以及对象的一些内部属性(因为嵌套的内部文档在模式上不同,所以它是更难做到)。因此,例如:
对于someType == 0
,我会寻找myDocument.innerObject.aCollectionOfStrings
,而与someType == 3
,我搜索每个myDocument.innerObject.aCollectionOfObjects
的myProp
财产。
在我的C#代码,如果我拉的全收集,然后用它LINQ操作,我有决定如何搜索完整的文档一个C#函数(基本上它检查的someType
的值,然后基于此,它知道要搜索的属性)以及它的嵌套文档,并且可以在C#代码中进行过滤。
然而,重构用建设者的过滤器后,我无法通过,C#语言过滤功能进入过滤器(很明显,因为所有的生成器正在做的是建立一个MongoDB的查询,我认为):
filter = filter & Builders<MyOwnType>.Filter.Eq(a => CheckIfObjectHasString(a, search), true);
凡CheckIfObjectHasString
是一样的东西:
private bool CheckIfObjectHasString(MyOwnType doc, string search)
{
if(doc.someType == 0)
{
return doc.innerObject.aCollectionOfStrings.Where(s => s.ToLower().Contains(search)).Any();
} else if(doc.someType == 3) {
return doc.innerObject.aCollectionOfObjects.Where(d => d.myProp.ToLower().Contains(search)).Any();
} else if(...)
{
// etc.
}
}
一个解决这个我想到了文件插入时也许是,在最顶层上创建some_collection
文件属性,T帽子拥有所有可搜索的材料,但这似乎是不洁的。我如何构建像上面这样的过滤器,而不是在LINQ或我刚刚提到的解决方案中进行处理?
我最终什么事做的是使原料BsonDocument
比较的,比得上我一直在寻找,并$or
荷兰国际集团他们,和嵌入在BsonDocuments
的$regex
为各自的领域。我不知道在MongoDB中搜索文档时,如果不使用应用程序代码,您的查询就是一个要与之比较的文档。
private BsonDocument FindSearch(string searchString)
{
// escape the searchString
var filterDocument = new BsonDocument();
var searchDocument = new BsonDocument();
searchDocument.Add(("$regex", $".*{searchString}.*"));
searchDocument.Add("$options", "i"); // to ignore case when performing the regex
var searchCriterias = new BsonArray(); // an array because I'll be $or-ing it
searchCriterias.Add(new BsonDocument("innerObject.aCollectionOfObjects.myProp", textSearch)); // access each nested object's property
searchCriterias.Add(new BsonDocument("innerObject.aCollectionOfStrings", textSearch)); // even though it's an array of strings, I can just search without having to iterate them
filterDocument.Add("$or", searchCriterias); // $or-ing it also saved me from having to check the existence of properties, before doing the search
}
然后,即使它是一个BsonDocument
,我能够与使用我已有Builders
Filter
小号例如为:
existingFilter = existingFilter | FindSearch(theSearch); // existingFilter is FilterDefinition<MyOwnType>