如何根据子对象的属性进行搜索

问题描述 投票:0回答:1

我有以下结构/代码,我正在尝试解决其中的一个问题。本来可以从一开始就采取不同的做法,但事实就是如此。

当搜索按部门 ID 获取所有员工时,员工应按照标签的 ASC 顺序在搜索中返回,除非标签为空,否则应将其发送到搜索底部。

这是结构关系

员工 部门编号 部门名称 标签
山姆 101 会计 “啊啊”
山姆 102 运输
蒂姆 101 会计 “哎呀”
蒂姆 102 运输 “zz”

和 json 视图:

{
    "Name": "Sam",
    "Departments": [
        {
            "ID": 101,
            "Name": "Accounting",
            "Tag": "aaa"
        },
        {
            "ID": 102,
            "Name": "Shipping",
            "Tag": Null
        },
    ]
  },
  {
    "Name": "Tim",
    "Departments" : [
        {
            "ID": 101,
            "Name": "Accounting",
            "Tag": "eee"
        },
        {
            "ID": 102,
            "Name": "Shipping",
            "Tag": "zzz"
        },
    ]
  }

因此,如果我正在搜索属于客户部门(101)的所有员工,由于 Sam 的 tagNumber 值为“aaa”,并且它位于 Tim 的标签为“eee”之前,那么 Sam 应该首先返回。 但如果我们搜索运输部门 (102),Sam 在该部门的标签号为空;并且蒂姆有该部门的标签编号值,那么蒂姆应该首先出现。

When searching by Accounting ID (101) ASC --> Tag number determines order (aaa is before eee)
   Sam
   Tim
When searching by Shipping ID (102) ASC --> Tag number Null goes to bottom. zzz has precedence over null and therfore, Tim should show up first
   Tim
   Sam

这就是当前创建文档和字段的方式:

var doc = new Document();
doc.Add(new Field("Name", "Sam", fieldStored));
doc.Add(new Field("Department.Id1", 101, fieldStored));
doc.Add(new Field("Department.Name1", "Accounting", fieldStored));
doc.Add(new Field("Department.Tag1", "aaa", fieldStored));
doc.Add(new Field("Department.Id2", 102, fieldStored));
doc.Add(new Field("Department.Name2", "Shipping", fieldStored));
doc.Add(new Field("Department.Tag2", null, fieldStored));

var doc = new Document();
doc.Add(new Field("Name", "Tim", fieldStored));
doc.Add(new Field("Department.Id1", 101, fieldStored));
doc.Add(new Field("Department.Name1", "Accounting", fieldStored));
doc.Add(new Field("Department.Tag1", "eee", fieldStored));
doc.Add(new Field("Department.Id2", 102, fieldStored));
doc.Add(new Field("Department.Name2", "Shipping", fieldStored));
doc.Add(new Field("Department.Tag2", "zzz", fieldStored));

我的搜索在TagComparer类中执行如下

public class TagComparator : FieldComparer<BytesRef>
{
    private readonly BytesRef[] bvalues;
    ..........................
    public override FieldComparer SetNextReader(AtomicReaderContext context)
    {
        sortedResults = FieldCache.DEFAULT.GetTermsIndex(context.AtomicReader, field);
        return this;
    }

    public override void Copy(int slot, int doc)
    {
        termCopy = new BytesRef();
        sortedResults.Get(doc, termCopy);
        bvalues[slot] = termCopy;
    }
}

问题摘要: 现在,它在运输部门 (102) 的 Tim 之前返回“Sam”,即使 Sam 的标签号为 Null,并且稍后返回“Tim”,即使他具有该部门的标签号值“zzz”。

我的尝试: 由于我的服务器分配了许多资源,因此我可以通过向复制覆盖方法添加更多代码来牺牲一点搜索速度。解决方案意味着:

  1. 在搜索者代码接管之前存储部门 ID

  2. 属于该部门的用户每点击一次,复制方法就会执行一次

  3. 获取显示部门 ID 和标签编号值的点击的完整文档

  4. 如果tagnumber有合法值,则显示正常,如果不合法,则显示在底部

         for (int i = 0; i < wholeDoc.GetValues("Department.Id").Length; i++)
         {
             if(int.Parse(wholeDoc.GetValues("Department.Id")[i]) == 1234) // department Id
             {
                 string tagNumber= wholeDoc.GetValues("TagNumber")[i];
                 if (string.IsNullOrWhiteSpace(tagNumber))
                     SetBottom(doc);
                 else 
                     bvalues[slot] = new BytesRef(wholeDoc.GetValues("TagNumber")[i]);
                 break;
             }
         }
    

这个解决方案有效,但问题是由于我添加的逻辑,它显着减慢了搜索速度。必须有一种方法让搜索者完成工作。如何告诉搜索者根据标签是否有值(根据我的数据结构)进行排序?或者是否必须在 Sam 和 ID1 之间创建文档,并为 Sam 和 ID2 创建一个完整的单独文档,等等与 Tim?

c# asp.net-core lucene.net
1个回答
0
投票

我不熟悉 Lucene,但 .NET 6 的“Windows Forms App”项目类型中的“Visual Studio 2022”中的以下几行给出了错误,并且编译器不接受 null。

var fieldStored = Field.Store.YES;
doc.Add(new Field("Department.Tag2", null, fieldStored)) 

doc.Add(new Field("Department.Tag2", null, fieldStored, Field.Index.NO));

无论如何,假设它接受 null,我认为可能在“TagComparer”类中,您应该重写以下方法并考虑 null 值:

int CompareValues(BytesRef first, BytesRef second)

int CompareValues(object first, object second)

int Compare(int slot1, int slot2)
© www.soinside.com 2019 - 2024. All rights reserved.