| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | 
							- package ii
 
- import (
 
- 	"context"
 
- 	"encoding/xml"
 
- 	"os"
 
- 	"slices"
 
- 	"time"
 
- 	"golib/v4/features/mo"
 
- 	"golib/v4/gio"
 
- )
 
- const (
 
- 	ConfigSuffix = ".xml"
 
- )
 
- // LoadItems 从 path 中读取并解析 XML 配置
 
- func LoadItems(path string) (Items, error) {
 
- 	name, err := gio.ReadDir(path, ConfigSuffix)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	items := make(ItemIndex)
 
- 	for i := 0; i < len(name); i++ {
 
- 		var itemInfo *ItemInfo
 
- 		itemInfo, err = ReadFile(name[i])
 
- 		if err != nil {
 
- 			return nil, err
 
- 		}
 
- 		items[itemInfo.Name] = itemInfo
 
- 	}
 
- 	return items, nil
 
- }
 
- // ReadFile 解析 name 至 ItemInfo
 
- // 如果需要 FieldInfo.Unique 生效, 需要调用 SetUnique
 
- func ReadFile(name string) (*ItemInfo, error) {
 
- 	b, err := os.ReadFile(name)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return ReadFrom(b)
 
- }
 
- func ReadFrom(b []byte) (*ItemInfo, error) {
 
- 	var itemInfo ItemInfo
 
- 	if err := xml.Unmarshal(b, &itemInfo); err != nil {
 
- 		return nil, err
 
- 	}
 
- 	if err := itemInfo.init(); err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return &itemInfo, nil
 
- }
 
- // SetUnique 设置唯一键
 
- // 注意: 为了降低初始化 XML 配置文件时的耦合度, 因此只能通过此方法设置唯一键. 如果通过软件实现唯一值, 那么将无法保证原子性
 
- // 实现方法: 取出已存在的 index, 然后与 ItemInfo 中的 uniqueMap 比较:
 
- // 删除 uniqueMap 中不存在的字段, 跳过 uniqueMap 中已存在的字段, 然后设置 uniqueMap 存在但 index 中不存在的字段为索引
 
- func SetUnique(info *ItemInfo, client *mo.Client) error {
 
- 	ctx, cancel := context.WithTimeout(context.Background(), mo.DefaultTimout)
 
- 	defer cancel()
 
- 	coll := client.Database(info.Name.Database()).Collection(info.Name.Collection())
 
- 	operator := coll.Indexes()
 
- 	cursor, err := operator.List(ctx)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	oldIndexMap, err := mo.ResolveIndexName(cursor)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	itemUniques := info.getUniques()
 
- 	for oldName := range oldIndexMap {
 
- 		if slices.Contains(itemUniques, oldName) {
 
- 			continue
 
- 		}
 
- 		// 删除 info 中不存在的索引
 
- 		if err = operator.DropOne(ctx, mo.IndexName(oldName)); err != nil {
 
- 			return err
 
- 		}
 
- 	}
 
- 	var indexList []mo.IndexModel
 
- 	for _, key := range itemUniques {
 
- 		if _, ok := oldIndexMap[key]; ok {
 
- 			continue
 
- 		}
 
- 		indexList = append(indexList, mo.NewIndex(key, true))
 
- 	}
 
- 	if len(indexList) == 0 {
 
- 		return nil
 
- 	}
 
- 	_, err = operator.CreateMany(ctx, indexList)
 
- 	return err
 
- }
 
- func SetItemsUnique(items Items, client *mo.Client) error {
 
- 	for _, item := range items.All() {
 
- 		if err := SetUnique(item, client); err != nil {
 
- 			return err
 
- 		}
 
- 	}
 
- 	return nil
 
- }
 
- func NewTime(d time.Duration) mo.DateTime {
 
- 	return mo.NewDateTimeFromTime(time.Now().Add(d))
 
- }
 
- func AppendTimeRange(matcher *mo.Matcher, start, end time.Time) {
 
- 	matcher.Gte(CreationTime, mo.NewDateTimeFromTime(start))
 
- 	matcher.Lte(CreationTime, mo.NewDateTimeFromTime(end))
 
- }
 
 
  |