sparql 有什么办法可以简化这个查询

sparql is there any way to make simplify this query

我构建了一个查询,它非常简单,但我的问题是我发现自己一次又一次地重复相同的三元组。

我有一个名为 TemporalContext 的 class,它的每个实例都有:

属性 canBeRecommendedFrom,(范围日期时间)

属性 canBeRecommendedUntil(日期时间范围)

或两者

每个实例 还可以 具有:

或者 属性 weightIfContextMatched

属性 weightIfContextDoesNotMatch

或两者

我想做的是:

  1. 如果 TemporalContext 的实例同时具有 canBeRecommendedFromcanBeRecommendedUtill,那么如果今天在该范围内,select weightIfContextMatched 的值,如果不是,select 的值为 weightIfontextDoesNotFound。但是,可能 weightIfContextMatchedweightIfContextDoesNotMatch 的值没有设置,所以我使用默认值。
  2. 如果 TemporalContext 的实例只有 canBeRecommendFrom 而没有 canBeRecommendUntil
  3. ,情况相同
  4. 相同的是 TemporalContext 的实例只有 canBeRecommendedUntill 而没有 canBeRecommendFrom

我查询了 TemporalContext 的实例同时具有 canBeRecommendedFromcanBeRecommendedUntil 以及 weightIfContextMatched 和 [=15= 的所有变体的情况]

这里是查询

select ?item ?finalTemporalWeight where
{
  values ?user {bo:ania} 
  #the items that have temporal context(s)
  {
    select ?item (SUM(?temporalWeight) as ?finalTemporalWeight) {
   ?item a rs:RecommendableClass .
      #to be sure that the item belongs to the class
      filter exists {
        ?item a ?itemClass
      }

  #the items that has both from and until temporal context
  {

    {
      #this block is if today is inside the range
      ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
      #to be sure that both until and from were set.
      ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .



      #check if today is before the until limit
      filter (now () < ?untilLimit)

      #check if today is after the from limit
      filter (now () > ?fromLimit)

     optional
    {
      ?tempoalContext rs:hasWeightIfContextMatched ?weight
    }
    bind((if(bound(?weight), ?weight, 1)) as ?temporalWeight)
    }
    union
    {
      #this block is if today is after the until limit
      ?tempoalContext a rs:TemporalContext .
    ?tempoalContext rs:appliedOnItems ?itemClass .
          #to be sure that both until and from were set.
    ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .



       #check if today is after the until limit
    filter (now () > ?untilLimit)

    optional
    {
     ?tempoalContext rs:hasWeightIfContextDoesNotMatch ?weight
    }
    bind((if(bound(?weight), ?weight, 0.1)) as ?temporalWeight)
    }
    union
    {
      #this block is if today is before the from limit
     ?tempoalContext a rs:TemporalContext .
    ?tempoalContext rs:appliedOnItems ?itemClass .
          #to be sure that both until and from were set.
    ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .



       #check if today is before the from limit
    filter (now () < ?fromLimit)

    optional
    {
      ?tempoalContext rs:hasWeightIfContextDoesNotMatch ?weight
    }
    bind((if(bound(?weight), ?weight, 0.3)) as ?temporalWeight)

    }

  }
  union
  #the items that has just from temporal context
  {

    {
    #this block is if today is before the from limit
      ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
      #to be sure that the from limit is set.
      ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .



      #to be sure that the until limit is not set.
      filter not exists {
        ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .
      }
      #check if today is before the from limit
      filter (now () < ?fromLimit)

     optional
    {
      ?tempoalContext rs:hasWeightIfContextDoesNotMatch ?weight
    }
    bind((if(bound(?weight), ?weight, 0.15)) as ?temporalWeight)

    }
    union
    {
      #this block is if today is after the from limit
      ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
      #to be sure that the from limit is set.
      ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .



      #to be sure that the until limit is not set.
      filter not exists {
        ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .
      }
      #check if today is before the from limit
      filter (now () > ?fromLimit)

     optional
    {
      ?tempoalContext rs:hasWeightIfContextMatched ?weight
    }
    bind((if(bound(?weight), ?weight, 0.25)) as ?temporalWeight)
    }
  }
  union
  #the items that has just until temporal context
  {
     {
    #this block is if today is before the until limit
      ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
      #to be sure that the until limit is set.

      ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .
      #to be sure that the from limit is not set.



      filter not exists {
        ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      }
      #check if today is before the until limit
      filter (now () < ?untilLimit)

     optional
    {
      ?tempoalContext rs:hasWeightIfContextMatched ?weight
    }
    bind((if(bound(?weight), ?weight, 0.35)) as ?temporalWeight)

    }
    union
    {
      #this block is if today is after the until limit
      ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
      #to be sure that the until limit is set.
      ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .


      #to be sure that the from limit is not set.
      filter not exists {
        ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      }
      #check if today is after the until limit
      filter (now () > ?untilLimit)

     optional
    {
      ?tempoalContext rs:hasWeightIfContextDoesNotMatch ?weight
    }
    bind((if(bound(?weight), ?weight, 0.45)) as ?temporalWeight)
    }
  }


      union
      #the items that have temporal context, but that temporal context has no canBeRecommendedFrom nor canBeRecommendedUntil
      {
    select distinct ?item ?temporalWeight {
      ?item a rs:RecommendableClass .
        ?tempoalContext a rs:TemporalContext .
      ?tempoalContext rs:appliedOnItems ?itemClass .
       ?item a ?itemClass .

        #to be sure that neight canBeRecommendFrom nor canBeRecommendedUntil is set
      filter not exists {
        ?tempoalContext rs:canBeRecommendedFrom ?fromLimit .
      }
        filter not exists {
                 ?tempoalContext rs:canBeRecommendedUntil ?untilLimit .
        }
        bind (4.4 as ?temporalWeight)
      }
} 

  }group by ?item
  }
  union
  #the items that don't have a temporal context, we will use the defalut value:
  {
    select distinct ?item ?finalTemporalWeight {
  ?item a rs:RecommendableClass .
    ?tempoalContext a rs:TemporalContext .
     ?tempoalContext rs:appliedOnItems ?itemClass .
    filter not exists {
    ?item a ?itemClass
    }
    bind (2.3 as ?finalTemporalWeight)
  }
  }

}
order by ?item

查询很简单但很长,我发现自己在每个联合中都重复同样的事情。现在我必须为第二种和第三种情况重复同样的事情,

我想在继续这个冗长但简单的查询之前我先问你也许你知道一个更好的方法来减少它的大小。

查询运行良好,我测试了它

更新 1

经过 @Joshua Taylor 的感谢回复后,结果如下:

但是,这是我的代码的结果:

可以看到第6行,该item没有任何值,该item的情况是:在from limit之前。所以正确的并集是#this block is if today is before the from limit。但是 hasWeightIfContextDoenNotMatch 没有值,所以我们应该使用默认值,即 0.3,我的代码这样做,我的答案中的代码没有。

更新 2

现在我完成了(并更新了查询)开发无聊的一般般无聊的查询,但我处理了所有场景,我会告诉你场景:

  1. 项目属于 temporalContext class:

1.1。 temporalClass 有 canBeRecommendFrom 和 canBeRecommendUntill

1.1.1。该项目在范围内

1.1.1.1。 weightIfContextMatched 存在。

1.1.1.2。 weightIfContextMatched 不存在。

1.1.2。该项目在起始限制之前。

1.1.2.1 weightIfContextDoesNotMatch 存在。

1.1.2.2。 weightIfContextDoesNotMatch 不存在。

1.1.3。该项目在直到限制之后。

1.1.3.1 weightIfContextDoesNotMatch 存在。

1.1.3.2。 weightIfContextDoesNotMatch 不存在。

1.2。 temporalClass 刚刚 canBeRecommendFrom

1.2.1 商品超出限制

1.2.1.1。 weightIfContextMatched 存在。

1.2.1.2。 weightIfContextMatched 不存在。

1.2.2 商品在起始限制之前

1.2.2.1 weightIfContextDoesNotMatch 存在。

1.2.2.2。 weightIfContextDoesNotMatch 不存在。

1.3。 temporalClass 刚刚 canBeRecommednFrom

1.3.1 商品在起始限制之前

1.3.1.1 weightIfContextDoesNotMatch 存在。

1.3.1.2。 weightIfContextDoesNotMatch 不存在。

1.3.2 商品超出限制

1.3.2.1。 weightIfContextMatched 存在。

1.3.2.2。 weightIfContextMatched 不存在。

1.4。 temporalClass 既没有 canBeRecommendFrom 也没有 canBeRecommendUntil

使用默认值(注意重复)

  1. 该项目不属于 temporalClass

使用默认值(注意重复)

您一直在寻找时间上下文,它是 TemporalContext,应用于项目 class,并且具有开始和结束限制,这样就可以从查询中得出。然后,您对根据 now() 是在间隔之前、期间还是之后使用的可选权重感兴趣。然后,如果我们在区间内,则将时间权重设置为匹配权重(或 1),如果我们在它之后,则设置为不匹配的权重(或 0.1),或者如果我们在其后,则设置为不匹配的权重(或 0.3)在它之前。我会用 bind 检查这些条件,并使用 coalesce 到 select 可选值或默认值:

SELECT  ?item ?temporalContext ?itemClass ?weight ?temporalWeight
WHERE
  { VALUES ?user { bo:ania }
    ?item a rs:RecommendableClass .

    ?temporalContext a rs:TemporalContext ;
      rs:appliedOnItems ?itemClass ;
      rs:canBeRecommendedFrom ?fromLimit ;
      rs:canBeRecommendedUntil ?untilLimit .

      OPTIONAL {
         ?temporalContext rs:hasWeightIfContextMatched ?matchedWeight
      }
      OPTIONAL {
        ?temporalContext rs:hasWeightIfContextDoesNotMatch ?unmatchedWeight
      }

      bind(if(now() < ?fromLimit,
              coalesce(?unmatchedWeight, 0.1),
              if(?fromLimit <= now() && now() <= ?untilLimit,
                 coalesce(?matchedWeight, 1.0),
                 if(?untilLimit < now(),
                    coalesce(?unmatchedWeight, 0.3),
                    0.0)))                           #-- default here?
           as ?temporalWeight)
  }
ORDER BY ?item

我使用 <= 检查 now() 是否 in持续时间,因为之前 if now() 正好等于其中一个,你可能没有抓住它。不过,您有可能到达 "default here?" 行吗?我认为如果数据实际上没有可比较的时间,它仍然是可能的。如我所见,您可以在那里使用默认值(如 0.0),或者您可以假设如果前两种情况不匹配,那么您只需要第三种,在这种情况下您可以完全跳过检查只需做:

  bind(if(now() < ?fromLimit,
          coalesce(?unmatchedWeight, 0.1),
          if(?fromLimit <= now() && now() <= ?untilLimit,
             coalesce(?matchedWeight, 1.0),
             coalesce(?unmatchedWeight, 0.3)))
      as ?temporalWeight)