Parsing MongoDB Collection Name from Object Field

Good day. I’m working on backend development with Golang and often write Aggregate code for MongoDB. I’m facing an issue where the collectionName field isn’t being parsed correctly. This field is in an object format, and while it parses well in other queries, it’s not working as expected in this particular query.

All the other values related to COLLECTION_SCHEMA_PATH are either in string or array format, and they are being retrieved correctly. It’s puzzling why only the data in the object isn’t coming through properly in this query.

If there’s anyone who can provide assistance, I would greatly appreciate it. Thank you.

this is My Code


	pipeLine := []bson.M{
		{"$match": bson.M{"user": req.User}},
		{"$addFields": bson.M{"subSetItems": bson.M{"$slice": []interface{}{"$items", req.StartIndex, req.EndIndex}}}},
		{"$unwind": bson.M{"path": "$subSetItems"}},
		{"$lookup": bson.M{
			"from": m.nfts.Name(),
			"let": bson.M{
				"address": "$subSetItems.collection",
				"tid":     "$subSetItems.tid",
			},
			"pipeline": []bson.M{{"$match": bson.M{"$expr": bson.M{"$and": []bson.M{
				{"$eq": []interface{}{"$address", "$$address"}},
				{"$eq": []interface{}{"$tid", "$$tid"}},
			}}}}},
			"as": NFT_SCHEMA,
		}},
		{"$unwind": bson.M{
			"path":                       NFT_SCHEMA_PATH,
			"preserveNullAndEmptyArrays": false,
		}},
		{"$lookup": bson.M{
			"from":         m.nftCollectibles.Name(),
			"localField":   "address",
			"foreignField": "subsetOfItems.collection",
			"as":           COLLECTION_SCHEMA,
		}},
		{"$unwind": bson.M{
			"path":                       COLLECTION_SCHEMA_PATH,
			"preserveNullAndEmptyArrays": false,
		}},
		{"$group": bson.M{
			"_id":               NFT_SCHEMA_PATH + "._id",
			"nftName":           bson.M{"$first": NFT_SCHEMA_PATH + ".name"},
			"tid":               bson.M{"$first": NFT_SCHEMA_PATH + ".tid"},
			"nftImage":          bson.M{"$first": NFT_SCHEMA_PATH + ".image"},
			"owner":             bson.M{"$first": NFT_SCHEMA_PATH + ".owner"},
			"currentPrice":      bson.M{"$first": NFT_SCHEMA_PATH + ".lastPrice"},
			"onSale":            bson.M{"$first": NFT_SCHEMA_PATH + ".onSale"},
			"mintDate":          bson.M{"$first": NFT_SCHEMA_PATH + ".mintDate"},
			"collectionAddress": bson.M{"$first": COLLECTION_SCHEMA_PATH + ".address"},
			"chain":             bson.M{"$first": COLLECTION_SCHEMA_PATH + ".relatedChain"},
			"collectionName":    bson.M{"$first": COLLECTION_SCHEMA_PATH + ".collectionName"},
			"contractName":      bson.M{"$first": COLLECTION_SCHEMA_PATH + ".contractName"},
			"collectionIcon":    bson.M{"$first": COLLECTION_SCHEMA_PATH + ".icon"},
		}},
		{"$sort": bson.M{"collectionAddress": -1, "tid": 1}},
	}

	if len(req.Search) != 0 {
		pipeLine = append(pipeLine, bson.M{"$match": bson.M{"$or": []bson.M{
			{"collectionAddress": bson.M{"$regex": req.Search}},
			{"collectionName": bson.M{"$regex": req.Search}},
			{"nftName": bson.M{"$regex": req.Search}},
		}}})
	}

	opt := options.Aggregate().SetAllowDiskUse(true).SetCollation(&options.Collation{
		Locale:          "en_US",
		NumericOrdering: true,
	})

	ctx := context.TODO()
	var result []*types.UserPageNft

	if cursor, err := m.userFavorite.Aggregate(ctx, pipeLine, opt); err != nil {
		return nil, err
	} else {
		defer cursor.Close(ctx)
		if err = cursor.All(ctx, &result); err != nil {
			return nil, err
		} else if len(result) == 0 {
			return nil, mongo.ErrNoDocuments
		} else {
			return result, nil
		}
	}

Hey @_WM2 thanks for the question!

You mentioned that “collectionName” is an object. However, $regex is documented to work only for strings. Do you match the “collectionName” object using $regex in other queries, or is it a field in the “collectionName” object?

Something else I noticed is that your sort may not always work as you expect. The underlying type for a bson.M is a Go map, which has explicitly random key order. The $sort operator is order-sensitive, so using a bson.M may result in undefined sort order depending on what order the map keys are marshaled when sending the command to the database.

I recommend changing

{"$sort": bson.M{"collectionAddress": -1, "tid": 1}},

to

{"$sort": bson.D{{"collectionAddress", -1}, {"tid", 1}}},