使用主键从 BaseX 中删除重复实体

delete duplicate entities from BaseX with a primary key

如何删除重复条目?

在这种情况下,Twitter 使用雪花作为推文 JSON 中的唯一 ID 字段,如下所示。按 ID 构建 index 条推文,然后删除每一条重复的 $tweet 条推文?但是如何不以递归方式删除每一条推文...?

A simple FLWOR 打印数据库中每条推文的 ID:

for $tweets  in db:open("twitter")
return <tweet>{$tweets/json/id__str}</tweet>

结果:

thufir@dur:~/flwor/twitter$ 
thufir@dur:~/flwor/twitter$ basex tweetID.xq 
<tweet>
  <id__str>1224165280068382720</id__str>
</tweet>
<tweet>
  <id__str>1224160851797643264</id__str>
</tweet>
<tweet>
  <id__str>1224134565280862208</id__str>
</tweet>
...
<tweet>
  <id__str>1224016596634603520</id__str>
</tweet>
<tweet>
  <id__str>1224001430417297410</id__str>
</tweet>
<tweet>
  <id__str>1223987662094249991</id__str>
</tweet>thufir@dur:~/flwor/twitter$ 
thufir@dur:~/flwor/twitter$ 

这里的重复是有意的,但正在寻找某种方式 "clean up" 数据库。

只是在寻找一个大纲或方法。我的想法是将一个 xquery 的输出通过管道传输到另一个 xquery ,但我对如何构建索引感到困惑。大概这是一个functionality built into the database itself, just need to leverage the correct module (probably).

--

这看起来 return 一个 different 结果,至少:

distinct-values(
    for $tweets in db:open("twitter") 
    return ($tweets/json/id__str))

尽管我不太确定它是所有 id__str 值的集合。

您可以在 FLOWER 中使用 group by 来获取重复项。它也应该比 distinct().

for $tweets  in db:open("twitter")
let $id := $tweets/json/id__str
group by $id
return
  if (count($tweets) > 1)
  then (for-each(tail($tweets), function ($tweet) { (: remove $tweet from DB :) } ) 
  else () (: nothing to do :)

我遇到了同样的问题并测试了这里已经讨论过的两种方法。这两种方法都可用于删除重复项,但存在性能差异。

  1. distinct-values 方法:

    (: Open database :)
    let $db := db:open('db-name')
    
    (: Get all distinct IDs :)
    let $ids := distinct-values($db/record/id)
    
    for $id in $ids
      (: Get all records with the same ID :)
      let $recsWithSameId := data($db/record/id)=$id
    
      (: Return only duplicate records :)
      return if (count($recsWithSameId)>1) then
        $recsWithSameId
    
        (: Instead of returning the duplicate records you can now delete all records except the one you want to keep. Then you removed the duplicates. :)
    
    
  2. group by 方法:

    for $recs in db:open('db-name')/record
      let $id := $recs/id
      group by $id
      return
        if (count($recs) > 1) then      
          $recs
          (: Instead of returning the duplicate records you can now delete all records except the one you want to keep. Then you removed the duplicates. :)
    

第二种方法 (group by) 比第一种 (distinct-values) 快得多。