2014-02-13 1 views
1

У меня есть 2 записи XML, оба одинаковы во всех значениях, кроме ID.Как подавить идентичные записи XML, имеющие разные идентификаторы?

<Record ID="2006-06-01"> 
    <author>sam</author> 
    <Year>2006</Year> 
    <Month>6</Month> 
</Record> 


<Record Id="2006-06-02"> 
    <author>sam</author> 
    <Year>2006</Year> 
    <Month>6</Month> 
</Record> 

Я хочу, чтобы подавить записи, то есть: я хочу только одна запись будет отображаться, когда я искать «Sam» в автора элемента, даже если идентификаторы отличаются использованием XQUERY & MarkLogic. Это возможно?? Если возможно, кто-нибудь это запросит.

Спасибо.

+0

Можете ли вы подробнее рассказать о прецеденте? Например, вам нужны эти «дубликаты» в системе? И какие результаты вы хотите показать (в более широком/функциональном смысле)? – grtjn

+0

, когда я ищу автора sam, обе записи отображаются на экране, эти 2 xmls кажутся одинаковыми, но разными в идентификаторах. На самом деле мы не будем выводить идентификатор конечному пользователю. Таким образом, конечный пользователь хочет отображать только одну запись, когда они ищут авторский сэм, даже если идентификаторы разные. – LSB

+0

Звучит немного так, как будто вы ищете уникальные значения, аналогичные грани поиска. Если это так, вы можете сделать что-то вроде 'distinct-values ​​(// author)' или 'cts: element-values ​​(xs: QName ('author')) .. .. – grtjn

ответ

0

Если бы атрибута не было, вы могли бы использовать deep-equal($node1, $node2). Примените это к каждому подузла в этих записях:

let $record1 := 
    <Record ID="2006-06-01"> 
    <author>sam</author> 
    <Year>2006</Year> 
    <Month>6</Month> 
    </Record> 
let $record2 := 
    <Record Id="2006-06-02"> 
    <author>sam</author> 
    <Year>2006</Year> 
    <Month>6</Month> 
    </Record> 

return $record1[not(
    every $node in $record1/* 
    satisfies deep-equal($node, $record2/*[local-name() = $node/local-name()]) 
)] 

Если нет поддержки определенных количественных выражений, вы должны преобразовать их в выражение FLWOR, но MarkLogic должны сделать во всех более поздних версий. Кроме того, это только проверяет дочерние узлы записей, если вы также хотите тестировать атрибуты (кроме @ID), вам нужно будет добавить тест для них.

1

Я думаю, вы можете просто просто использовать это, он находит все записи, где автор содержит строку «sam», а затем возвращает только первый.

(//Record[contains(author, "sam")])[1] 
+0

С помощью MarkLogic, который также может использовать полнотекстовый индекс : 'cts: search (collection(), cts: element-word-query (xs: QName (" author ")," sam ")) [1]' – mblakele

0

Можно удалить эти дубликаты, но удаление дубликатов не будет хорошо масштабироваться.

Как указано в Jens Erat, вы можете использовать fn:deep-equal или какой-либо другой тест на равенство (но не fn:distinct-nodes). Или я, вероятно, использовал бы элемент map:map для отслеживания отдельных ключей и дешифрования этих ключей. Это может выглядеть примерно так:

let $m := map:map() 
for $n in $results 
let $key := $n/author||'/'||$n/Year||'/'||$n/Month 
where not(map:contains($m, $key)) 
return (
    map:put($m, $key, true()), 
    $n) 

Но как вы можете видеть эти подходы требует поиска на каждом узле, который не является хорошей производительности. Если вы заботитесь о производительности, вы должны реструктурировать свою базу данных, чтобы URI были уникально уникальны. Например, если ваш URI был чем-то вроде /records/{ $author }/{ $year }/{ $month }, тогда было бы невозможно иметь такое дублирование.

Смежные вопросы