欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于netcore对ElasitSearch客户端NEST查询功能的简单封装NEST.Repository

程序员文章站 2022-06-23 16:18:57
NEST.Repository A simple encapsulation with NEST client for search data form elasticsearch. github API NESTReaderRepository TEntity Get(TKey id); TEnt ......

NEST.Repository

A simple encapsulation with NEST client for search data form elasticsearch.

github

API

NESTReaderRepository

TEntity Get(TKey id);
TEntity Get(Func<QueryContainerDescriptor<TEntity>, QueryContainer> filterExp = null,
            Func<SourceFilterDescriptor<TEntity>, ISourceFilter> includeFieldExp = null,
            Expression<Func<TEntity, object>> sortExp = null, SortOrder sortType = SortOrder.Ascending);
Tuple<long, List<TEntity>> GetList(Func<QueryContainerDescriptor<TEntity>, QueryContainer> filterExp = null,
            Func<SourceFilterDescriptor<TEntity>, ISourceFilter> includeFieldExp = null,
            Expression<Func<TEntity, object>> sortExp = null, SortOrder sortType = SortOrder.Ascending
           , int limit = 10, int skip = 0)

NESTReaderRepositoryAsync

Task<TEntity> GetAsync(TKey id);
Task<TEntity> GetAsync(Func<QueryContainerDescriptor<TEntity>, QueryContainer> filterExp = null,
            Func<SourceFilterDescriptor<TEntity>, ISourceFilter> includeFieldExp = null,
            Expression<Func<TEntity, object>> sortExp = null, SortOrder sortType = SortOrder.Ascending);
Task<Tuple<long, List<TEntity>>> GetListAsync(Func<QueryContainerDescriptor<TEntity>, QueryContainer> filterExp = null,
            Func<SourceFilterDescriptor<TEntity>, ISourceFilter> includeFieldExp = null,
            Expression<Func<TEntity, object>> sortExp = null, SortOrder sortType = SortOrder.Ascending
           , int limit = 0, int skip = 0)

Depend on

NEST 6.0.2
Repository.IEntity 2.0.1 (or you can write IEntity<T> interface and you entity inherit it.)

How to Use

First, you need have an entity inherit IEntity<T>, T is type of PrimaryKey. eg

[Serializable]
[BsonIgnoreExtraElements]
public class User : IEntity<long>
{
    [BsonId]
    public long ID { get; set; }

    public double Age { get; set; }

    public double Sex { get; set; }

    public string Like { get; set; }
}

Second, you need have a repository inherit NESTReaderRepository or NESTReaderRepositoryAsync. eg

public class UserRepo : NESTReaderRepository<User, long>
{
    public static string connString = "http://localhost:9200/";

    public UserRepo()
        : base(connString)
    {

    }
}

Now, you can search data with simple api. eg

 static void Main(string[] args)
 {
    Repository.Container.RepositoryContainer.Register<UserRepo>();
    var userRepo = Repository.Container.RepositoryContainer.Resolve<UserRepo>();

    var user = userRepo.Get(9);
    var users = userRepo.GetList(
        filterExp: q => +q.Range(r => r.Field(f => f.Age).GreaterThan(13).LessThan(28)), 
        includeFieldExp: p => p.Includes(i => i.Fields(f => f.Age, f => f.Sex, f => f.Like)),
        sortExp: s => s.Age,
        sortType: Nest.SortOrder.Ascending,
        limit: 100,
        skip: 0
    );
 }

How to write a Query

0x00. Structured Search

By default, documents will be returned in _score descending order, where the _score for each hit is the relevancy score calculated for how well the document matched the query criteria.

q => q.DateRange(r => r
    .Field(f => f.{Field with DateTime Type})
    .GreaterThanOrEquals(new DateTime(2017, 01, 01))
    .LessThan(new DateTime(2018, 01, 01))
)

The benefit of executing a query in a filter context is that Elasticsearch is able to forgo calculating a relevancy score, as well as cache filters for faster subsequent performance.

 q => q.Bool(b => b.Filter(bf => bf
    .DateRange(r => r
        .Field(f => f.{Field with DateTime Type})
        .GreaterThanOrEquals(new DateTime(2017, 01, 01))
        .LessThan(new DateTime(2018, 01, 01))
        )
    )
)

0x01. Unstructured Search

Full text queries (find all documents that contain "Russ" in the lead developer first name field)

q => q.Match(m => m
    .Field(f => f.LeadDeveloper.FirstName)
    .Query("Russ")
)

0x02. Combining Search

q => q.Bool(b => b
    .Must(mu => mu
        .Match(m => m
            .Field(f => f.LeadDeveloper.FirstName)
            .Query("Russ")
        ), mu => mu
        .Match(m => m
            .Field(f => f.LeadDeveloper.LastName)
            .Query("Cam")
        )
    )
    .Filter(fi => fi
        .DateRange(r => r
            .Field(f => f.StartedOn)
            .GreaterThanOrEquals(new DateTime(2017, 01, 01))
            .LessThan(new DateTime(2018, 01, 01))
        )
    )
)

use operator

q => q.Match(m => m
        .Field(f => f.LeadDeveloper.FirstName)
        .Query("Russ")
    ) && q
    .Match(m => m
        .Field(f => f.LeadDeveloper.LastName)
        .Query("Cam")
    ) && +q
    .DateRange(r => r
        .Field(f => f.StartedOn)
        .GreaterThanOrEquals(new DateTime(2017, 01, 01))
        .LessThan(new DateTime(2018, 01, 01))
    )
)

Should ==> OR ==> ||
Must ==> And ==> &&
Must_Not ==> NOT==> !
Filter ==> +

the query will be converted to a bool query if use any operator, and the answer to the bool query is always yes or no , so that will not score.

Reference

https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-queries.html

https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html