Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为不同类型的嵌套文档制作一个动态生成器过滤器-MongoDB C#Driver_C#_Mongodb_Mongodb Query_Filtering - Fatal编程技术网

为不同类型的嵌套文档制作一个动态生成器过滤器-MongoDB C#Driver

为不同类型的嵌套文档制作一个动态生成器过滤器-MongoDB C#Driver,c#,mongodb,mongodb-query,filtering,C#,Mongodb,Mongodb Query,Filtering,我有一个名为some\u collection的收藏。some_collection的模式如下:(模式由C#DTO指定) 在我的C#代码中,innerObject是一个抽象类,有多个子类。这些子类具有不同的属性,因此MongoDB集合中的文档并不完全相同。它们所属的子类的类型由单个some\u集合文档中的someType字段划分。因此,audit_collection中包含两种不同类型嵌套文档的两个文档示例: { _id: ObjectId('first'),

我有一个名为
some\u collection
的收藏。
some_collection
的模式如下:(模式由C#DTO指定)

在我的C#代码中,innerObject是一个抽象类,有多个子类。这些子类具有不同的属性,因此MongoDB集合中的文档并不完全相同。它们所属的子类的类型由单个
some\u集合
文档中的
someType
字段划分。因此,
audit_collection
中包含两种不同类型嵌套文档的两个文档示例:

   {
       _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.acollectionofstring
,而对于
someType==3
,我会搜索每个
myDocument.innerObject.aCollectionOfObjects
myProp
属性

在我的C#代码中,如果我提取完整集合,然后对其使用LINQ操作,我有一个C#函数,它确定如何搜索完整文档(基本上它检查
someType
的值,然后根据该值,它知道要搜索哪些属性),以及它的嵌套文档,并可以在C#代码中进行过滤

但是,在使用构建器过滤器进行重构之后,我无法将C#filter函数传递到过滤器中(显然,因为构建器所做的只是构建一个MongoDB查询,我认为):

filter=filter&Builders.filter.Eq(a=>checkifobjecthastring(a,search),true);

其中,
CheckIfObjectHaString
类似于:

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_集合
文档上创建一个属性,该属性包含所有可搜索的材料,但似乎不干净。我如何构建如上所述的过滤器,而不必使用LINQ或我刚才提到的解决方案进行处理d?

我最终做的是使原始的
BsonDocument
s与我正在寻找的内容相比较,并
$or
将它们隐藏起来,并将
$regex
嵌入
BsonDocuments
中,用于各自的字段。我不知道在MongoDB中搜索文档时,在不使用应用程序代码的情况下,您的查询y是一个要比较的文档

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
,我也能够将它与我已经存在的
构建器
过滤器一起使用,例如:

existingFilter=existingFilter|FindSearch(theSearch);//existingFilter是filter定义

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
}