如何在 C# Mongodb 强类型驱动程序中基于嵌套数组元素创建索引

lem*_*mon 5 c# mongodb mongodb-.net-driver

这个问题与这个问题的原理完全相同,但是当该对象嵌套在集合的数组中时,我想在对象属性上使用强类型方法创建索引。

我可以用:

new CreateIndexModel<T>( Builders<T>.IndexKeys.Ascending( a ) )
Run Code Online (Sandbox Code Playgroud)

其中a是访问直接属性的表达式。

但我没有发现类似的内容:

Builders<Library>.Filter.ElemMatch(x => x.Author.Books, b => b.IsVerified == false));
Run Code Online (Sandbox Code Playgroud)

这样我就可以将嵌套在数组中的对象的某些字段定义为索引,该数组是集合的成员。

是否可以做到以及如何做到?

Enr*_*one 5

考虑以下数据模型:

public class Course
{
   public string Name { get; set; }
   public string Teacher { get; set; }
}

public class Student
{
  public string Name { get; set; }
  public int Age { get; set; }
  public ReadOnlyCollection<Course> Courses { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式在字段 Courses 上创建升序多键索引:

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp1
{
  public static class Program
  {
    private static MongoClient Client;
    private static IMongoDatabase Database;
    private static IMongoCollection<Student> Collection;

    public static async Task Main(string[] args)
    {
      Client = new MongoClient();
      Database = Client.GetDatabase("test-index");
      Collection = Database.GetCollection<Student>("students");

      var courses1 = new List<Course>()
      {
        new Course { Name = "Math", Teacher = "Bob" }
      }.AsReadOnly();

      var courses2 = new List<Course>()
      {
        new Course { Name = "Computer Science", Teacher = "Alice" }
      }.AsReadOnly();

      var mark = new Student
      {
        Name = "Mark",
        Courses = courses1,
        Age = 20
      };

      var lucas = new Student
      {
        Name = "Lucas",
        Courses = courses2,
        Age = 22
      };

      await Collection.InsertManyAsync(new[] { mark, lucas }).ConfigureAwait(false);


      var model = new CreateIndexModel<Student>(
        Builders<Student>.IndexKeys.Ascending(s => s.Courses));

      await Collection.Indexes.CreateOneAsync(model).ConfigureAwait(false);

      Console.WriteLine("All done !");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

此查询由您创建的索引提供服务: db.students.find({Courses: {"Name": "Math", "Teacher": "Bob"}})

如果您不想在整个数组 Courses 上创建索引,而是希望在嵌套对象(Course 对象)的字段 Name 上创建索引,则可以这样做:

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp1
{
  public static class Program
  {
    private static MongoClient Client;
    private static IMongoDatabase Database;
    private static IMongoCollection<Student> Collection;

    public static async Task Main(string[] args)
    {
      Client = new MongoClient();
      Database = Client.GetDatabase("test-index");
      Collection = Database.GetCollection<Student>("students");

      var courses1 = new List<Course>()
      {
        new Course { Name = "Math", Teacher = "Bob" }
      }.AsReadOnly();

      var courses2 = new List<Course>()
      {
        new Course { Name = "Computer Science", Teacher = "Alice" }
      }.AsReadOnly();

      var mark = new Student
      {
        Name = "Mark",
        Courses = courses1,
        Age = 20
      };

      var lucas = new Student
      {
        Name = "Lucas",
        Courses = courses2,
        Age = 22
      };

      await Collection.InsertManyAsync(new[] { mark, lucas }).ConfigureAwait(false);


      var model = new CreateIndexModel<Student>(
        Builders<Student>.IndexKeys.Ascending("Courses.Name"));

      await Collection.Indexes.CreateOneAsync(model).ConfigureAwait(false);

      Console.WriteLine("All done !");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

此查询由您创建的索引提供服务:db.students.explain("executionStats").find({"Courses.Name": "Math"})

在我的第二个示例中避免使用魔术字符串的一种可能方法是利用 nameof C# 运算符的强大功能: $"{nameof(Student.Courses)}.{nameof(Course.Name)}"