tag_service.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import uuid
  2. from typing import Optional
  3. from flask_login import current_user
  4. from sqlalchemy import func
  5. from werkzeug.exceptions import NotFound
  6. from extensions.ext_database import db
  7. from models.dataset import Dataset
  8. from models.model import App, Tag, TagBinding
  9. class TagService:
  10. @staticmethod
  11. def get_tags(tag_type: str, current_tenant_id: str, keyword: Optional[str] = None) -> list:
  12. query = (
  13. db.session.query(Tag.id, Tag.type, Tag.name, func.count(TagBinding.id).label("binding_count"))
  14. .outerjoin(TagBinding, Tag.id == TagBinding.tag_id)
  15. .where(Tag.type == tag_type, Tag.tenant_id == current_tenant_id)
  16. )
  17. if keyword:
  18. query = query.where(db.and_(Tag.name.ilike(f"%{keyword}%")))
  19. query = query.group_by(Tag.id, Tag.type, Tag.name, Tag.created_at)
  20. results: list = query.order_by(Tag.created_at.desc()).all()
  21. return results
  22. @staticmethod
  23. def get_target_ids_by_tag_ids(tag_type: str, current_tenant_id: str, tag_ids: list) -> list:
  24. # Check if tag_ids is not empty to avoid WHERE false condition
  25. if not tag_ids or len(tag_ids) == 0:
  26. return []
  27. tags = (
  28. db.session.query(Tag)
  29. .where(Tag.id.in_(tag_ids), Tag.tenant_id == current_tenant_id, Tag.type == tag_type)
  30. .all()
  31. )
  32. if not tags:
  33. return []
  34. tag_ids = [tag.id for tag in tags]
  35. # Check if tag_ids is not empty to avoid WHERE false condition
  36. if not tag_ids or len(tag_ids) == 0:
  37. return []
  38. tag_bindings = (
  39. db.session.query(TagBinding.target_id)
  40. .where(TagBinding.tag_id.in_(tag_ids), TagBinding.tenant_id == current_tenant_id)
  41. .all()
  42. )
  43. if not tag_bindings:
  44. return []
  45. results = [tag_binding.target_id for tag_binding in tag_bindings]
  46. return results
  47. @staticmethod
  48. def get_tag_by_tag_name(tag_type: str, current_tenant_id: str, tag_name: str) -> list:
  49. if not tag_type or not tag_name:
  50. return []
  51. tags = (
  52. db.session.query(Tag)
  53. .where(Tag.name == tag_name, Tag.tenant_id == current_tenant_id, Tag.type == tag_type)
  54. .all()
  55. )
  56. if not tags:
  57. return []
  58. return tags
  59. @staticmethod
  60. def get_tags_by_target_id(tag_type: str, current_tenant_id: str, target_id: str) -> list:
  61. tags = (
  62. db.session.query(Tag)
  63. .join(TagBinding, Tag.id == TagBinding.tag_id)
  64. .where(
  65. TagBinding.target_id == target_id,
  66. TagBinding.tenant_id == current_tenant_id,
  67. Tag.tenant_id == current_tenant_id,
  68. Tag.type == tag_type,
  69. )
  70. .all()
  71. )
  72. return tags or []
  73. @staticmethod
  74. def save_tags(args: dict) -> Tag:
  75. if TagService.get_tag_by_tag_name(args["type"], current_user.current_tenant_id, args["name"]):
  76. raise ValueError("Tag name already exists")
  77. tag = Tag(
  78. id=str(uuid.uuid4()),
  79. name=args["name"],
  80. type=args["type"],
  81. created_by=current_user.id,
  82. tenant_id=current_user.current_tenant_id,
  83. )
  84. db.session.add(tag)
  85. db.session.commit()
  86. return tag
  87. @staticmethod
  88. def update_tags(args: dict, tag_id: str) -> Tag:
  89. if TagService.get_tag_by_tag_name(args.get("type", ""), current_user.current_tenant_id, args.get("name", "")):
  90. raise ValueError("Tag name already exists")
  91. tag = db.session.query(Tag).where(Tag.id == tag_id).first()
  92. if not tag:
  93. raise NotFound("Tag not found")
  94. tag.name = args["name"]
  95. db.session.commit()
  96. return tag
  97. @staticmethod
  98. def get_tag_binding_count(tag_id: str) -> int:
  99. count = db.session.query(TagBinding).where(TagBinding.tag_id == tag_id).count()
  100. return count
  101. @staticmethod
  102. def delete_tag(tag_id: str):
  103. tag = db.session.query(Tag).where(Tag.id == tag_id).first()
  104. if not tag:
  105. raise NotFound("Tag not found")
  106. db.session.delete(tag)
  107. # delete tag binding
  108. tag_bindings = db.session.query(TagBinding).where(TagBinding.tag_id == tag_id).all()
  109. if tag_bindings:
  110. for tag_binding in tag_bindings:
  111. db.session.delete(tag_binding)
  112. db.session.commit()
  113. @staticmethod
  114. def save_tag_binding(args):
  115. # check if target exists
  116. TagService.check_target_exists(args["type"], args["target_id"])
  117. # save tag binding
  118. for tag_id in args["tag_ids"]:
  119. tag_binding = (
  120. db.session.query(TagBinding)
  121. .where(TagBinding.tag_id == tag_id, TagBinding.target_id == args["target_id"])
  122. .first()
  123. )
  124. if tag_binding:
  125. continue
  126. new_tag_binding = TagBinding(
  127. tag_id=tag_id,
  128. target_id=args["target_id"],
  129. tenant_id=current_user.current_tenant_id,
  130. created_by=current_user.id,
  131. )
  132. db.session.add(new_tag_binding)
  133. db.session.commit()
  134. @staticmethod
  135. def delete_tag_binding(args):
  136. # check if target exists
  137. TagService.check_target_exists(args["type"], args["target_id"])
  138. # delete tag binding
  139. tag_bindings = (
  140. db.session.query(TagBinding)
  141. .where(TagBinding.target_id == args["target_id"], TagBinding.tag_id == (args["tag_id"]))
  142. .first()
  143. )
  144. if tag_bindings:
  145. db.session.delete(tag_bindings)
  146. db.session.commit()
  147. @staticmethod
  148. def check_target_exists(type: str, target_id: str):
  149. if type == "knowledge":
  150. dataset = (
  151. db.session.query(Dataset)
  152. .where(Dataset.tenant_id == current_user.current_tenant_id, Dataset.id == target_id)
  153. .first()
  154. )
  155. if not dataset:
  156. raise NotFound("Dataset not found")
  157. elif type == "app":
  158. app = (
  159. db.session.query(App)
  160. .where(App.tenant_id == current_user.current_tenant_id, App.id == target_id)
  161. .first()
  162. )
  163. if not app:
  164. raise NotFound("App not found")
  165. else:
  166. raise NotFound("Invalid binding type")