func (tf *typeFilter) Save() ([]datastore.Property, error) {
	props := []datastore.Property{}
	for name, propList := range tf.pm {
		if len(name) != 0 && name[0] == '$' {
			continue
		}
		multiple := len(propList) > 1
		for _, prop := range propList {
			toAdd := datastore.Property{
				Name:     name,
				Multiple: multiple,
				NoIndex:  prop.IndexSetting() == ds.NoIndex,
			}
			switch prop.Type() {
			case ds.PTBytes:
				v := prop.Value().([]byte)
				if prop.IndexSetting() == ds.ShouldIndex {
					toAdd.Value = datastore.ByteString(v)
				} else {
					toAdd.Value = v
				}
			case ds.PTKey:
				toAdd.Value = dsF2R(prop.Value().(ds.Key))
			case ds.PTBlobKey:
				toAdd.Value = appengine.BlobKey(prop.Value().(bs.Key))
			case ds.PTGeoPoint:
				toAdd.Value = appengine.GeoPoint(prop.Value().(ds.GeoPoint))
			default:
				toAdd.Value = prop.Value()
			}
			props = append(props, toAdd)
		}
	}
	return props, nil
}
func dsF2RProp(ctx context.Context, in ds.Property) (datastore.Property, error) {
	err := error(nil)
	ret := datastore.Property{
		NoIndex: in.IndexSetting() == ds.NoIndex,
	}
	switch in.Type() {
	case ds.PTBytes:
		v := in.Value().([]byte)
		if in.IndexSetting() == ds.ShouldIndex {
			ret.Value = datastore.ByteString(v)
		} else {
			ret.Value = v
		}
	case ds.PTKey:
		ret.Value, err = dsF2R(ctx, in.Value().(*ds.Key))
	case ds.PTBlobKey:
		ret.Value = appengine.BlobKey(in.Value().(bs.Key))
	case ds.PTGeoPoint:
		ret.Value = appengine.GeoPoint(in.Value().(ds.GeoPoint))
	default:
		ret.Value = in.Value()
	}
	return ret, err
}
Beispiel #3
0
			for _, v := range vs {
				ss, err := s.SearchService.ByView(ctx, v)
				if err != nil {
					return err
				}

				if len(ss) != 0 {
					continue
				}

				err = s.SearchService.Create(ctx, &Search{
					Name:     "#now",
					ViewID:   v.ID,
					Query:    "#now AND IsArchived: false",
					ViewRank: datastore.ByteString("0"),
				})
				if err != nil {
					return err
				}

				err = s.SearchService.Create(ctx, &Search{
					Name:     "Incoming",
					ViewID:   v.ID,
					Query:    "NOT #now AND NOT #next AND NOT #later AND IsArchived: false",
					ViewRank: datastore.ByteString("1"),
				})
				if err != nil {
					return err
				}
Beispiel #4
0
func (s *SearchService) Create(ctx context.Context, se *Search) error {
	span := trace.FromContext(ctx).NewChild("trythings.search.Create")
	defer span.Finish()

	if se.ID != "" {
		return fmt.Errorf("se already has id %q", se.ID)
	}

	if se.CreatedAt.IsZero() {
		se.CreatedAt = time.Now()
	}

	if se.Name == "" {
		return errors.New("Name is required")
	}

	if se.ViewID == "" {
		return errors.New("ViewID is required")
	}

	v, err := s.ViewService.ByID(ctx, se.ViewID)
	if err != nil {
		return err
	}

	if se.SpaceID == "" {
		se.SpaceID = v.SpaceID
	}

	if se.SpaceID != v.SpaceID {
		return errors.New("Search's SpaceID must match View's")
	}

	if len(se.ViewRank) != 0 {
		return fmt.Errorf("se already has a view rank %x", se.ViewRank)
	}

	// TODO#Performance: Add a shared or per-request cache to support these small, repeated queries.

	if se.Query == "" {
		return errors.New("Query is required")
	}

	rootKey := datastore.NewKey(ctx, "Root", "root", 0, nil)

	// Create a ViewRank for the search.
	// It should come after every other search in the view.
	var ranks []*struct {
		ViewRank datastore.ByteString
	}
	_, err = datastore.NewQuery("Search").
		Ancestor(rootKey).
		Filter("ViewID =", se.ViewID).
		Project("ViewRank").
		Order("-ViewRank").
		Limit(1).
		GetAll(ctx, &ranks)
	if err != nil {
		return err
	}

	maxViewRank := MinRank
	if len(ranks) != 0 {
		maxViewRank = Rank(ranks[0].ViewRank)
	}
	rank, err := NewRank(maxViewRank, MaxRank)
	if err != nil {
		return err
	}
	se.ViewRank = datastore.ByteString(rank)

	ok, err := s.IsVisible(ctx, se)
	if err != nil {
		return err
	}

	if !ok {
		return errors.New("cannot access view to create search")
	}

	id, _, err := datastore.AllocateIDs(ctx, "Search", nil, 1)
	if err != nil {
		return err
	}
	se.ID = fmt.Sprintf("%x", id)

	k := datastore.NewKey(ctx, "Search", se.ID, 0, rootKey)
	k, err = datastore.Put(ctx, k, se)
	if err != nil {
		return err
	}

	return nil
}