Как найти повторяющиеся данные в документе XML с помощью XQuery? - PullRequest
0 голосов
/ 15 января 2009

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

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

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

Ответы [ 4 ]

2 голосов
/ 30 июля 2013

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

for $c in doc()//colors может привести к ошибке РАСШИРЕННОЕ КУШКА ДЕРЕВА в больших наборах данных.

Вот несколько более сложный способ атаковать это, когда данные огромны, убедитесь, что URI Lexicon включен *1009*, а затем добавьте индекс диапазона элемента на элемент 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

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

1 голос
/ 26 января 2009

Для этого 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 

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

1 голос
/ 12 января 2010

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

for $c in doc()//colors
where fn:count($c/color) != fn:count(fn:distinct-values($c/color))
return $c
1 голос
/ 15 января 2009

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

for $doc in doc()
let $colors = $doc//color/string(.)
where some $color in $colors
      satisfies count($colors[. = $color] > 1)
return doc()
...