我有一个名为some_collection
的集合。 some_collection
的架构是这样的:(架构由C#DTO决定)
{
_id: ObjectId(.....),
firstName: "fName",
lastName: "lName",
someType: 4,
innerObject: {
// see below
}
}
在我的C#代码中,innerObject是一个抽象类,并且有多个子类。这些子类具有变体属性,因此MongoDB集合中的文档并不完全相同。它们所属的子类的类型由单个someType
文档中的some_collection
字段划分。因此,audit_collection
中包含2种不同类型嵌套文档的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
的{{1}属性。
在我的C#代码中,如果我拉完整个集合,然后对它使用LINQ操作,我有一个C#函数来确定如何来搜索整个文档(基本上它会检查值myProp
,然后基于此,知道要搜索的属性)及其嵌套文档,并且可以在C#代码中进行过滤。
然而,在重构使用Builders Filters之后,我无法将该C#过滤器函数传递给Filter(显然,因为所有Builder正在构建一个MongoDB查询,我认为):
someType
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.
}
}
文档上创建一个属性,它具有所有可搜索的材料,但这似乎是不洁净的。如何构建一个类似上面的过滤器,而无需在LINQ或我刚才提到的解决方案中进行处理?
答案 0 :(得分:0)
我最终做的是将原始numpy.nan == numpy.nan
与我要查找的内容相比较BsonDocument
,并将$or
嵌入到$regex
中他们各自的领域。我不知道在MongoDB中搜索文档而不使用应用程序代码时,您的查询是一个要比较的文档。
BsonDocuments
然后,即使它是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