Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/28.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
Angular 使用角度管道实现自定义搜索相关性_Angular_Pipe_Angular Pipe - Fatal编程技术网

Angular 使用角度管道实现自定义搜索相关性

Angular 使用角度管道实现自定义搜索相关性,angular,pipe,angular-pipe,Angular,Pipe,Angular Pipe,我目前有一个带有自定义管道过滤器的基本课程搜索功能。它根据课程标题、说明或关键字中是否存在匹配项返回结果,但它以任意顺序返回课程。我想首先修改管道以返回更相关的结果,优先顺序是搜索查询在1中匹配。标题,2。描述,3。关键词 一些测试用例示例: 查询“chinese”当前返回“1X chinese”之前的“1 French”,因为“1 French”的关键字与“chinese”匹配 查询“线性代数”首先返回54 Math,然后返回89A statistics,即使后者在所有3个字段中都匹配 实施这

我目前有一个带有自定义管道过滤器的基本课程搜索功能。它根据
课程标题
说明
关键字
中是否存在匹配项返回结果,但它以任意顺序返回课程。我想首先修改管道以返回更相关的结果,优先顺序是搜索查询在1中匹配。标题,2。描述,3。关键词

一些测试用例示例:

  • 查询
    “chinese”
    当前返回
    “1X chinese”
    之前的
    “1 French”
    ,因为
    “1 French”
    的关键字与
    “chinese”
    匹配

  • 查询
    “线性代数”
    首先返回
    54 Math
    ,然后返回
    89A statistics
    ,即使后者在所有3个字段中都匹配

  • 实施这一计划的最佳方式是什么?我目前正在研究,这意味着我可以尝试用以下逻辑(伪代码)定义我自己的比较器

    这种观点包括

      <li *ngFor="let course of courses | courseFilter: searchText |
     orderBy: ['title', 'description', ''keywords]">
    
    
    
    然而,我对Angular比较陌生,实现细节超出了我目前的理解范围。这是最直接的方法吗?如果我知道我只是在过滤课程对象,是否可以在不定义第二个orderBy管道的情况下修改当前课程过滤管道


    任何提示都将不胜感激

    您首先要将排名添加到每门课程中,然后按此顺序排序。i、 e

    addRank(a: Course, query: string): number{
    
        var rank: number;
        if(course.course_title.toUpperCase().includes(query)) rank += 5;
        if(course.description.toUpperCase().includes(query)) rank += 3;
        if(course.keywords.toUpperCase().includes(query)) rank += 1;
        course.rank = rank
    
    然后按该排名按降序排列:

    
    
    但是,AngularJs(与AngularJs/Angular 1不同)不提供orderBy或filter,他们建议您自己在组件中执行这些操作,而不是使用管道:

    Angular不提供用于筛选或排序列表的管道。 熟悉AngularJS的开发人员将其称为filter和orderBy。 在角度上没有等价物

    这不是疏忽。Angular不提供此类管道,因为它们 表现不佳,防止过度缩小

    参考:

    注意这一点,您可能会使用一个单独的courseResults列表,它是courses数组的过滤和排序版本。当然,在输入任何搜索/筛选条件之前,您可以将其初始化为课程。您还可以通过在搜索输入中添加一个按钮来最小化不必要的搜索/筛选调用(如果您是按键入方式进行的;如果您是按按钮单击进行的,那么您将跳过该操作)

    简单解决方案:

    因此,在你的StackBlitz的基础上,我完全不用管道,做了一个新的:

    
    
    我们不显示所有课程,但显示课程结果…:

    。。。初始化为空或所有课程(如下所示):

    公共课程结果:课程[]=this.courses;
    
    然后搜索可以是:

    搜索($event){
    this.courseResults=this.sortByRank(this.rankAndFilter(this.courses,this.searchText.toUpperCase());
    }
    私有筛选器(课程:课程[],查询:字符串){
    var结果=[];
    变量秩:个数;
    为了(让我们来上课程){
    秩=0;
    if(course.course_title.toUpperCase().includes(query)){rank+=5};
    if(course.description.toUpperCase().includes(query)){rank+=3};
    if(course.keywords.toUpperCase().includes(query)){rank+=1};
    course.rank=等级;
    如果(排名>0)结果推送(路线);
    }      
    返回结果;
    }
    私人分拣银行(课程:课程[]){
    返回课程。排序(函数(a:课程,b:课程){
    返回b.rank-a.rank;
    });
    }
    
    扩展解决方案:

    [编辑]一个新的应用程序,它使用debounce(因此,如果用户输入速度非常快,则不会对每次击键进行整个筛选和排序)和distinctUntilChanged(如果用户将字符退格,则不会麻烦),并创建了数组的全局扩展(sortBy和sortByDesc)

    现在我们有了输入:

    
    
    然后将该ViewChild作为ElementRef获取:

    @ViewChild('searchInput')searchInputRef:ElementRef;
    
    然后在init之后,我们在本机元素上设置输入上的observable,并订阅它:

    ngAfterViewInit(){
    var subscription=fromEvent(this.searchInputRef.nativeElement,'input').pipe(
    映射((e:KeyboardEvent)=>(e.target).value),
    去BounceTime(400),
    distinctUntilChanged()
    //开关映射(()=>this.performSearch())
    );
    订阅。订阅(数据=>{
    此。性能搜索(数据);
    });
    }  
    私人performSearch(搜索文本){
    console.log(“搜索:+searchText”);
    this.searchText=searchText;
    this.courseResults=this.rankAndFilter(this.courses,searchText).sortByDesc('rank');
    返回此.courseResults;
    }
    
    感谢您的帮助,我用您的建议更新了,但无法获得所需的输出。我做错了什么?非常感谢。啊,直到你在这里再次指出,我才注意到你的闪电战。通过适当的更改进行更新。当然,将需要精细化,但这是出于性能和最小化原因(即远离使用管道)的基本方法。您可以分享您的分叉链接吗?我更深入地研究了角度应用程序中的过滤和排序数据,并对将过滤逻辑移动到组件本身进行了修改(如您所建议的),但在实现排序逻辑时遇到了困难。谢谢@Matt I已经为简单版本和使用debounce和distinctUntilChanged(也是阵列的全局扩展)的版本提供了StackBlitz分叉
      <li *ngFor="let course of courses | courseFilter: searchText |
     orderBy: ['title', 'description', ''keywords]">
    
    addRank(a: Course, query: string): number{
    
        var rank: number;
        if(course.course_title.toUpperCase().includes(query)) rank += 5;
        if(course.description.toUpperCase().includes(query)) rank += 3;
        if(course.keywords.toUpperCase().includes(query)) rank += 1;
        course.rank = rank