| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 | package iiimport (	"context"	"encoding/xml"	"os"	"slices"	"golib/v3/features/mo"	"golib/v3/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 生效, 需要调用 SetUniquefunc 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	}	indexMap, err := mo.ResolveIndexName(cursor)	if err != nil {		return err	}	uniques := info.getUniques()	for idx := range indexMap {		if slices.Contains(uniques, idx) {			continue		}		// 删除 info 中不存在的索引		if _, err = operator.DropOne(ctx, idx); err != nil {			return err		}	}	var needAdd []mo.IndexModel	for _, key := range uniques {		if _, ok := indexMap[mo.IndexName(key)]; ok {			continue		}		needAdd = append(needAdd, mo.NewIndex(key, true))	}	if len(needAdd) == 0 {		return nil	}	_, err = operator.CreateMany(ctx, needAdd)	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}
 |