Slick

2013-02-25 93 views
5

के साथ रिकर्सिव पेड़ जैसी तालिका क्वेरी मेरा टेबल डेटा एक पेड़ संरचना बनाता है जहां एक पंक्ति एक ही तालिका में मूल पंक्ति को संदर्भित कर सकती है।Slick

मैं स्लिम का उपयोग करके हासिल करने की कोशिश कर रहा हूं, एक प्रश्न लिखना है जो एक पंक्ति और उसके सभी बच्चों को वापस कर देगा। इसके अलावा, मैं वही करना चाहूंगा, लेकिन एक प्रश्न लिखूंगा जो एक बच्चे और उसके सभी पूर्वजों को वापस कर देगा।

दूसरे शब्दों में:

findDown(1) लौटना चाहिए

List(Group(1, 0, "1"), Group(3, 1, "3 (Child of 1)")) 

findUp(5) लौटना चाहिए

List(Group(5, 2, "5 (Child of 2)"), Group(2, 0, "2")) 

यहाँ एक पूरी तरह कार्यात्मक वर्कशीट (लापता समाधान ;-) के अलावा है।

package com.exp.worksheets 

import scala.slick.driver.H2Driver.simple._ 

object ParentChildTreeLookup { 

    implicit val session = Database.forURL("jdbc:h2:mem:test1;", driver = "org.h2.Driver").createSession() 

    session.withTransaction { 
    Groups.ddl.create 
    } 

    Groups.insertAll(
    Group(1, 0, "1"), 
    Group(2, 0, "2"), 
    Group(3, 1, "3 (Child of 1)"), 
    Group(4, 3, "4 (Child of 3)"), 
    Group(5, 2, "5 (Child of 2)"), 
    Group(6, 2, "6 (Child of 2)")) 

    case class Group(
    id: Long = -1, 
    id_parent: Long = -1, 
    label: String = "") 

    object Groups extends Table[Group]("GROUPS") { 
    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc) 
    def id_parent = column[Long]("ID_PARENT") 
    def label = column[String]("LABEL") 
    def * = id ~ id_parent ~ label <> (Group, Group.unapply _) 
    def autoInc = id_parent ~ label returning id into { 
     case ((_, _), id) => id 
    } 

    def findDown(groupId: Long)(implicit session: Session) = { ??? } 

    def findUp(groupId: Long)(implicit session: Session) = { ??? } 
    } 

} 

एक findDown पर वास्तव में बुरा है, और स्थिर प्रयास की तरह कुछ हो सकता है:

private def groupsById = for { 
    group_id <- Parameters[Long] 
    g <- Groups; if g.id === group_id 
} yield g 

private def childrenByParentId = for { 
    parent_id <- Parameters[Long] 
    g <- Groups; if g.id_parent === parent_id 
} yield g 


def findDown(groupId: Long)(implicit session: Session) = { groupsById(groupId).list union childrenByParentId(groupId).list } 

लेकिन, मुझे आईडी और id_parent का उपयोग कर स्लिक के लिए एक तरह से रिकर्सिवली एक ही तालिका में खोज करने के लिए देख रहा हूँ संपर्क। समस्या को हल करने के लिए कोई अन्य अच्छे तरीके वास्तव में स्वागत है। हालांकि ध्यान रखें, डेटाबेस राउंड-ट्रिप की संख्या को कम करना सबसे अच्छा होगा।

+0

आप एसक्यूएल में ऐसा कैसे करेंगे? – EECOLOR

उत्तर

-1

सादे एसक्यूएल में यह मुश्किल होगा। आपके पास कई विकल्प होंगे:

  1. सही रिकॉर्ड एकत्र करने के लिए संग्रहीत प्रक्रिया का उपयोग करें (पुनरावर्ती)। तब
  2. सभी रिकॉर्ड का चयन करें और के रूप में वर्णित here और here (Optimized SQL for tree structures से) कोड
  3. और अधिक उन्नत तकनीक
  4. उपयोग का उपयोग कर एक पेड़ से उन कन्वर्ट कोड का उपयोग कर एक पेड़ से उन रिकॉर्ड को परिवर्तित। फिर उन रिकॉर्ड्स को कोड

का उपयोग करके पेड़ में रूपांतरित करें, जिस तरह से आप SQL में ऐसा करना चाहते हैं, आपको एक स्लिम क्वेरी बनाना होगा। Leaky Abstractions की अवधारणा यहां बहुत स्पष्ट है।

तो वृक्ष संरचना हो रही दो चरणों की आवश्यकता:

  1. (नियमित रूप से कोड का उपयोग कर) सही (या सभी रिकॉर्ड)
  2. बिल्ड जाओ उन रिकॉर्ड से एक पेड़

आप कर रहे हैं के बाद से Slick का उपयोग करके मुझे नहीं लगता कि यह एक विकल्प है, लेकिन एक अन्य डेटाबेस प्रकार आपके डेटा मॉडल के लिए बेहतर फिट हो सकता है। विभिन्न प्रकारों के बीच अंतर के लिए NoSQL देखें।

+0

धन्यवाद। अतीत में मैंने डेटाबेस की तरफ संग्रहीत प्रक्रियाओं का उपयोग करके इस प्रकार की चीज की है, लेकिन यहां मेरे पेड़ों की गहराई आम तौर पर उथल-पुथल होगी, हालांकि रिकॉर्ड-सेट काफी बड़ा हो सकता है। आप अनुमान लगाने में शायद सही हैं कि यह कोड-साइड समाधान होने में समाप्त होगा, और नोएसक्यूएल इस परियोजना के लिए एक विकल्प नहीं है। मैं उम्मीद कर रहा था कि स्लिम उपयोगकर्ताओं को इस समस्या को हल करने के लिए एक इष्टतम तरीका या अच्छा पैटर्न मिला है जो अन्य स्लिम प्रश्नों (कंपोज़िबिलिटी इत्यादि पर विचार करने) के साथ अच्छी तरह से फिट बैठता है – Jack

+2

रिकर्सिव एसक्यूएल/पदानुक्रमित प्रश्न कुछ ऐसा नहीं है जो SQL डेटाबेस अक्षम हैं काम करने का। उदाहरण के लिए एच 2 अपने रिकर्सिव सीटीई के साथ एसक्यूएल मानक का समर्थन करता है, इसलिए प्रश्न वास्तव में स्लिम में रिकर्सिव सीटीई को व्यक्त करने के तरीके के बारे में है। –

+1

यहां [प्रासंगिक एच 2 दस्तावेज अनुभाग] है (http://www.h2database.com/html/advanced.html#recursive_queries) –

2

आप एसक्यूएल को स्लिम से कॉल करने का प्रयास कर सकते हैं।एसक्यूएल कॉल जाने के लिए ऊपर पदानुक्रम कुछ इस तरह (यह एसक्यूएल सर्वर के लिए है) दिखेगा:

WITH org_name AS 
(
    SELECT DISTINCT 
     parent.id AS parent_id, 
     parentname.label as parent_label, 
     child.id AS child_id, 
     childname.ConceptName as child_label 
    FROM 
     Group parent RIGHT OUTER JOIN 
     Group child ON child.parent_id = parent.id 
), 
jn AS 
( 
    SELECT 
     parent_id, 
     parent_label, 
     child_id, 
     child_label 
    FROM 
     org_name 
    WHERE 
     parent_id = 5 
    UNION ALL 
     SELECT 
      C.parent_id, 
      C.parent_label, 
      C.child_id, 
      C.child_label 
     FROM 
      jn AS p JOIN 
      org_name AS C ON C.child_id = p.parent_id 
) 
SELECT DISTINCT 
    jn.parent_id, 
    jn.parent_label, 
    jn.child_id, 
    jn.child_label 
FROM 
    jn 
ORDER BY 
    1; 

आप लाइन बदलने के पदानुक्रम नीचे जाना चाहते हैं:

org_name AS C ON C.child_id = p.parent_id 

को

org_name AS C ON C.parent_id = p.child_id 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^