Как найти повторяющиеся данные в XML-документе с помощью XQuery?

У меня есть куча документов в базе данных MarkLogic xml. В одном документе есть:

<colors>
  <color>red</color>
  <color>red</color>
</colors>

Наличие нескольких цветов не является проблемой. Наличие нескольких цветов, которые оба красные, является проблемой. Как найти документы с повторяющимися данными?


person Community    schedule 15.01.2009    source источник


Ответы (4)


Все, что возвращает MarkLogic, — это просто последовательность узлов, поэтому мы можем подсчитать размер последовательности целого и сравнить его с количеством последовательности отдельных значений. Если они не отличаются друг от друга, они дублируются, и у вас есть свое подмножество.

for $c in doc()//colors
where fn:count($c/color) != fn:count(fn:distinct-values($c/color))
return $c
person Community    schedule 11.01.2010
comment
В зависимости от ваших потребностей в масштабировании, это довольно быстро исчерпает память. См. подход только для индекса ниже - person derickson; 30.07.2013

Это должно сработать. Я не слишком знаком с MarkLogic, поэтому первая строка для получения набора документов может быть неправильной. Это вернет все документы, которые имеют 2 или более цветовых элемента с одинаковым строковым значением.

for $doc in doc()
let $colors = $doc//color/string(.)
where some $color in $colors
      satisfies count($colors[. = $color] > 1)
return doc()
person Community    schedule 15.01.2009
comment
Является ли перебор всех документов единственным выходом? - person Sixty4Bit; 15.01.2009

Или вы можете сделать это полностью из индексов :)

for $c in doc()//colors может вызвать ошибку EXPANDED TREE CACHE для больших наборов данных.

Вот немного более сложный способ атаки, когда данные огромны: убедитесь, что лексикон URI включен, а затем добавьте индекс диапазона элементов к элементу >color и вычислить различные значения цвета, которые где-то дублируются. Затем последовательно перебираем только те документы, которые имеют этот цвет, и вычисляем количество элементов интересующих цветов в документах. Если вы получаете частоту больше 1, этот документ нуждается в дедупликации.

let $qn := xs:QName("color")
let $colorsWithItemFreq := cts:element-values($qn, (), ("ascending", "item-order", "item-frequency"))
let $colorsOfInterest := 
    for $color at $i in cts:element-values($qn, (), ("ascending", "item-order", "fragment-frequency"))
    let $fragFrequency := cts:frequency($color)
    let $itemFrequency := cts:frequency($colorsWithItemFreq[$i])
    where $itemFrequency gt $fragFrequency
    return 
        $color

for $uri in cts:uris( (), ("document"), cts:element-value-query($qn, $colorsOfInterest)
let $colorsWithDuplicationInThisDoc :=
    for $color in cts:element-values($qn, (), ("item-frequency"), cts:document-query($uri) )
    where $color = $colorsOfInterest and cts:frequency($color) gt 1
    return
        $color
where fn:count( $colorsWithDuplicationInThisDoc ) gt 1
return
    $uri

Надеюсь, это поможет.

person Community    schedule 30.07.2013

Для этого XML:

<?xml version="1.0"?>
<colors>
    <color>Red</color>
    <color>Red</color>
    <color>Blue</color>
</colors>

Используя этот XSD:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method = "text" />  
    <xsl:strip-space elements="*"/>

    <xsl:template match="colors">

        <xsl:for-each select="color">
            <xsl:variable name="node_color" select="text()"/>
            <xsl:variable name="numEntries" select="count(../color[text()=$node_color])"/>
            <xsl:if test="$numEntries &gt; 1">
                <xsl:text>Color value of </xsl:text><xsl:value-of select="."/><xsl:text> has multiple entries &#xa;</xsl:text>      
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Я получил этот вывод:

Color value of Red has multiple entries 
Color value of Red has multiple entries 

Так что, по крайней мере, они будут найдены, но будут сообщать о каждом появлении повторяющегося цвета, а не только о каждом повторяющемся цвете.

person Stephen Friederichs    schedule 26.01.2009