问题描述
UPDATE si
SET si.iCurrentStock = si.iCurrentStock +
(
SELECT
SUM(
(CASE
WHEN ttd2.vEffectType = 'Add' THEN ttd2.iLeafQuantity
WHEN ttd2.vEffectType = 'Subtract' THEN ttd2.iLeafQuantity * -1
ELSE 0
END)
)
FROM tblTransactionDetail ttd2
WHERE ttd2.iTransactionId = @p_TransactionId
AND ISNULL(ttd2.bIsstockUpdated,0) = 0
),ttd.bIsstockUpdated = 1
FROM dbo.tblStoreItem si
INNER JOIN dbo.tblTransactionDetail ttd ON si.iItemId = ttd.iItemId
WHERE si.iStoreId = @v_StoreId
AND ttd.iTransactionId = @p_TransactionId
AND ISNULL(ttd.bIsstockUpdated,0) = 0;
我正在尝试使用 Lucene.NET 为这些文档编制索引。我创建了一个表示这些 JSON 条目的类。
{"id":3121,"name":"Nikon AF-S DX Nikkor 35 mm","brand": "Nikon","price": 456.32}
{"id":3122,"name":"Canon EF-S 55-250 mm","brand": "Canon","price": 500.98}
我可以打开 JSON 条目,将其转换为 Lens 对象,然后创建一个 Lucene 文档。
[<climutable>]
type Lens =
{ Id: int; Name: string; Brand: string; Price: Float}
这有效,我可以将文档添加到索引并进行搜索。当我想更新索引中的文档而不是添加它时,问题就开始了。
let getDocument (inputDocument:Lens) =
let id = StoredField("id",inputDocument.Id)
let name = TextField("name",inputDocument.Name,Field.Store.YES)
let brand = StoredField("brand",inputDocument.Brand)
let price = StoredField("price",inputDocument.Price)
let doc = Document()
doc.Add(id)
doc.Add(name)
doc.Add(brand)
doc.Add(price)
// return
doc
文档说我必须用 id 字段创建一个术语,并使用 .GetStringValue() 作为术语并调用 .UpdateDocument(term,doc)。但是,这不起作用,每次调用 upsertDocument 时都会添加一个新文档。
int32 数据库 id 的最佳字段类型是什么,我如何在索引更新操作中使用它来覆盖上一个条目?
单个文件中的完整工作流程:
Core 更适合作为要点:
https://gist.github.com/l1x/91c36b867acc70e8486a6bce7899332a
Update0:有点好笑。它不会重现该错误。
Update1:我可以可靠地重现该错误。关键是调用IndexWriter.commit()。通过检查文档可以看到重复。
搜索 Nikon 或 Canon 会产生许多文档。这些都具有相同的 ID。
let upsertDocument (writer:IndexWriter) (doc:Document) =
try
let id = doc.GetField("id").GetStringValue()
let term = Term("id",id)
writer.UpdateDocument(term,doc)
writer.Flush(triggerMerge = false,applyAllDeletes = false)
Ok "Ok"
with ex ->
logger
<| sprintf "Exception : %s" ex.Message
logger
<| sprintf "Exception : %A" ex.StackTrace
Error ex.Message
重复:
> searcherz.Search(query,20).scoreDocs;;
val it : scoreDoc [] =
[|doc=5 score=1.1118877 shardindex=-1 {Doc = 5;
score = 1.111887693f;
Shardindex = -1;};
doc=6 score=1.1118877 shardindex=-1 {Doc = 6;
score = 1.111887693f;
Shardindex = -1;};
doc=7 score=1.1118877 shardindex=-1 {Doc = 7;
score = 1.111887693f;
Shardindex = -1;};
doc=8 score=1.1118877 shardindex=-1 {Doc = 8;
score = 1.111887693f;
Shardindex = -1;}|]
解决方法
好的,我想我明白了。问题是您无法通过使用 Term
将整数 ID 转换为字符串(例如 GetStringValue
)来创建有效的 "3122"
。相反,您必须从 ID 的原始字节(例如 [60 8 0 0 18 31]
)创建术语,如下所示:
open Lucene.Net.Util
let id = doc.GetField("id").GetInt32Value().Value
let bytes = BytesRef(NumericUtils.BUF_SIZE_INT32)
NumericUtils.Int32ToPrefixCodedBytes(id,bytes)
let term = Term("id",bytes)
进行此更改后,我不再在索引中看到重复的文档。有关详细信息,请参阅 this SO question。