How to create a new Mongo DB collection

Sometimes developers need to store some new entities in Juju DB. This document provides key points for adding a new collection to MongoDB.

Contents:

Define a new collection in Juju DB

All collections are represented in the package state. This package enables reading, observing, and changing the state stored in MongoDB of a whole model managed by juju.

A developer can define a new collection in: https://github.com/juju/juju/blob/develop/state/allcollections.go

Example of a new collection definition:

...
// ----------------------
newEntitiesC: {
   indexes: []mgo.Index{{
      Key: []string{"model-uuid", "unit-id"},
   }},
},
...
newEntitiesC = "newEntities"

Define a new entity collection structure

Create a golang file in the state subfolder: state/new_entites.go

Add state shim to interact with the Juju global state in your API:

// NewEntitiesState returns the new entities for the current state.
func (st *State) NewEntityState() *new EntityPersistence {
	return &newEntityPersistence{
		st: st,
	}
}
// serviceLocatorPersistence provides the persistence
// functionality for service locators.
type serviceLocatorPersistence struct {
	st *State
}

Define a logger to be able to write logs from your API:

var neLogger = logger.Child("new-entity")

Define a New Entity structure:

type NewEntity struct {
	st  *State
	doc newEntityDoc
}

Define the document structure for the new MongoDB collection:

type newEntityDoc struct {
	DocId              string                 `bson:"_id"`
	Id                 int                    `bson:"id"`
	UnitId             string                 `bson:"unit-id"`
	Param1             string                 `bson:"param-1"`
	Param2             string                 `bson:"param-2"`
	OtherParams        map[string]interface{} `bson:"other-params"`
      ...
}

Develop an API to manipulate collection entities

You then need to implement methods that will help you interact with new collection docs. Let’s define some simple CRUD methods for ‘new entity’.

Add a new doc

Here is an example of a way to add a new doc to a MongoDB collocation:

// AddNewEntity creates a new entity record, which ...
func (ne *newEntityPersistence) AddNewEntity(args params.AddNewEntityParams) (*NewEntity, error) {
	id, err := sequenceWithMin(sp.st, "new-entity", 1)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer errors.DeferredAnnotatef(&err, "cannot add new entity %q", args.Name)

	model, err := ne.st.Model()
	if err != nil {
		return nil, errors.Trace(err)
	} else if model.Life() != Alive {
		return nil, errors.Errorf("model is no longer alive")
	}

	newEntityDoc := newEntityDoc{
		DocId:              fmt.Sprintf("%s.%s", args.Name, args.UnitId),
		Id:                 id,
		Param1:             args.Param1,
		Param2:             args.Param2,
		UnitId:             args.UnitId,
		Params:             args.Params,
	}
	buildTxn := func(attempt int) ([]txn.Op, error) {
		// If we've tried once already and failed, check that
		// model may have been destroyed.
		if attempt > 0 {
			if err := checkModelActive(sp.st); err != nil {
				return nil, errors.Trace(err)
			}
			return nil, errors.AlreadyExistsf("new entity name: %s unit-id: %s", args.Name, args.UnitId)
		}
		ops := []txn.Op{
			model.assertActiveOp(),
			{
				C:      newEntitiesC,
				Id:     newEntityDoc.DocId,
				Assert: txn.DocMissing,
				Insert: &newEntityDoc,
			},
		}
		return ops, nil
	}
	if err = sp.st.db().Run(buildTxn); err != nil {
		return nil, errors.Trace(err)
	}
	return &NewEntity{doc: newEntityDoc}, nil
}

Remove a new doc

Here is an example of a way to remove a new doc from a MongoDB collocation:

// RemoveNewEntities removes a service locator record
func (ne *newEntitiesPersistence) RemoveNewEntity(neId string) []txn.Op {
	op := txn.Op{
		C:      newEntitiesC,
		Id:     neId,
		Remove: true,
	}
	return []txn.Op{op}
}

Last updated 1 year, 8 months ago. Help improve this document in the forum.