我有以下结构/代码,我正在尝试解决其中的一个问题。本来可以从一开始就采取不同的做法,但事实就是如此。
当搜索按部门 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”。
我的尝试: 由于我的服务器分配了许多资源,因此我可以通过向复制覆盖方法添加更多代码来牺牲一点搜索速度。解决方案意味着:
在搜索者代码接管之前存储部门 ID
属于该部门的用户每点击一次,复制方法就会执行一次
获取显示部门 ID 和标签编号值的点击的完整文档
如果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?
我不熟悉 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)