planetarium / mimir

A backend service that provides 9c-related utility APIs.
https://nine-chronicles.dev/
GNU Affero General Public License v3.0
4 stars 22 forks source link

Implement avatarAddress filter for `agent` field #489

Open Atralupus opened 4 days ago

Atralupus commented 4 days ago

Currently, the Agent query only supports searches by the agent's address. However, users often need to find an agent by checking if a given avatarAddress exists in the AvatarAddresses field.

Desired Query Example:

query {
  agent(hasAvatarAddress: "166d25Df718A73861EEe8DA3495929300FB7DE71") {
    address
    object {
      avatarAddresses
    }
  }
}

Implementation Steps:

1. Update AgentRepository

Add a new method FindByAvatarAddressAsync to check if the given avatarAddress exists within the AvatarAddresses field.

example:

public async Task<AgentDocument> FindByAvatarAddressAsync(Address avatarAddress)
{
    var collectionName = CollectionNames.GetCollectionName<AgentDocument>();
    var collection = dbService.GetCollection<AgentDocument>(collectionName);

    var filter = Builders<AgentDocument>.Filter.Or(
        Builders<AgentDocument>.Filter.Eq("Object.AvatarAddresses.0", avatarAddress),
        Builders<AgentDocument>.Filter.Eq("Object.AvatarAddresses.1", avatarAddress),
        Builders<AgentDocument>.Filter.Eq("Object.AvatarAddresses.2", avatarAddress)
    );

    var document = await collection.Find(filter).FirstOrDefaultAsync();
    if (document is null)
    {
        throw new DocumentNotFoundInMongoCollectionException(
            collection.CollectionNamespace.CollectionName,
            $"'Address' equals to '{avatarAddress.ToHex()}'"
        );
    }

    return document;
}

2. Update Query

Modify the GraphQL Query class to include a parameter hasAvatarAddress and add the logic for searching using this new parameter.

example:

    public async Task<AgentState> GetAgentAsync(
        Address? address,
        Address? hasAvatarAddress,
        [Service] AgentRepository repo
    )
    {
        if (address is not null)
        {
            return (await repo.GetByAddressAsync(address.Value)).Object;
        }
        else if (hasAvatarAddress is not null)
        {
            var agent = await repo.FindByAvatarAddressAsync(hasAvatarAddress.Value);
            if (agent is null)
            {
                throw new ArgumentException($"No agent found with avatarAddress: {hasAvatarAddress}");
            }
            return agent.Object;
        }
        else
        {
            throw new ArgumentException("Either address or hasAvatarAddress must be provided.");
        }
    }

3. Setup Local Database

4. Test Cases