Can I remove GeoCoordinates from a record?

Description

I have a collection with a GeoCoordinates property like this one:

Property(name="location", data_type=DataType.GEO_COORDINATES)

And I can successfully set the property with collection.data.update, but I don’t know how to clear it. The use-case would be a user first setting the location in my app, but then deciding he wants to remove it.

I am assuming this can be done because I can create records without that property and I see it is set to null, but I tried updating it with a null value but I saw no effect (the old location was not deleted). This is how I did it (note that I am using the typescript client):

collection.data.update({
    id: "id",
    properties: { location: null }
})

I also tried location: {}, but didn’t work either.

And two related questions:

  • Are records that don’t have a location set ignored when I try to filter by geocoordinates?
  • Can I sort the results by a distance computed between a geo-coordinate property and an arbitrary location?

Server Setup Information

I am using a free managed cluster.

Hi! I assume you are using typescript v3, right?

Regarding your questions:

  • Yes, when it will only look for objects that has that same geo property

About your second question, I am not entirely sure, but I don’t think this is possible.

At this stage, this not yet a search, but a filtering.

But this would be a nice feature to have. Can you go ahead and open a feature request?

Thanks!

Hi!

I was not able to reproduce this. Here is the code I used:

import weaviate, { Collection, WeaviateClient, generateUuid5 } from 'weaviate-client';

// Connect to Weaviate
// The client performs I/O during initialisation so these methods all return promises
// You can either await them or use .then() to handle the result

// This is the simplest way to connect to Weaviate
// const client: WeaviateClient = await weaviate.connectToLocal();
// weaviate.connectToLocal().then((client) => { ... });

async function runFullExample() {
  const client = await weaviate.connectToLocal({
    host: process.env.WEAVIATE_HOST || 'localhost',
    port: parseInt(process.env.WEAVIATE_PORT || '8080'),
    grpcPort: parseInt(process.env.WEAVIATE_GRPC_PORT || '50051'),
    headers: { 'X-OpenAI-Api-Key': process.env.OPENAI_API_KEY as string }, // Replace with your inference API key
  });
  const cleanRun = true; // change this to false if you don't want to delete the collection each run
  initCollection(client, "Geo", cleanRun)
    .then(importData)
    .then(async (collection) => {
      await RemoveGeoPropertyValue(
        collection
      );
    });
  // We use promise chaining here because each step depends on the successful completion of the previous step
  // The data won't import successfully unless the collection has been created
  // Likewise we can't show the data unless it has been imported
  // To ensure there are no race conditions, we chain the promises together guaranteeing that each step is completed before the next one starts
}

////// Helper functions for runFullExample //////

function collectionExists(client: WeaviateClient, collection_name:string): Promise<boolean> {
  // Check if the collection already exists
  return client.collections.exists(collection_name);
}

function getCollection(client: WeaviateClient, collection_name:string): Collection {
  return client.collections.get(collection_name);
}

async function createCollection(client: WeaviateClient, collection_name:string): Promise<Collection> {
  // let's create the class
  const collection = await client.collections.create({
    name: collection_name,
    properties: [
      {
        name: 'city',
        dataType: 'text',
      },
      {
        name: 'location',
        dataType: 'geoCoordinates',
      },
    ],
  });
  console.log(`Successfully created collection: ${collection.name}!`);

  return collection;
}

function deleteCollection(client: WeaviateClient, collection_name:string) {
  // Delete the collection if it already exists
  return collectionExists(client, collection_name).then((exists) =>
    exists ? client.collections.delete(collection_name) : Promise.resolve()
  );
}

async function importData(collection: Collection): Promise<Collection> {
  // Here we import our data using the `.insertMany` method
  // This method batches the data for us in the background
  // first, let's grab our Jeopardy Questions from the interwebs
  const res = await collection.data.insertMany([
        {
            properties: {"city": "Belo Horizonte", "location": {"latitude": -19.912998, "longitude": -43.940933}},
            id: generateUuid5("belo horizonte")   
        },
        {
            properties: {"city": "Amsterdam", "location": {"latitude": 52.3676, "longitude": 4.9041}},
            id: generateUuid5("amsterdam")
        }
    ]);
  if (res.hasErrors) {
    throw new Error(`Failed to import data: ${JSON.stringify(res.errors, null, 2)}`);
  }
  return collection;
}

function initCollection(client: WeaviateClient, collection_name:string, cleanRun: boolean): Promise<Collection> {
  // Here we initialise the collection
  // We can either delete the collection and create it from scratch
  // Or we can check if it exists and create it if it doesn't
  // The `cleanRun` parameter allows us to choose between these two options
  if (cleanRun) {
    console.log('Cleaning and creating collection anew');
    return deleteCollection(client, collection_name).then(() => createCollection(client, collection_name));
  } else {
    console.log('Creating collection if it does not exist');
    return collectionExists(client, collection_name).then((exists) =>
      exists ? Promise.resolve(getCollection(client, collection_name)) : createCollection(client, collection_name)
    );
  }
}

function RemoveGeoPropertyValue(collection: Collection) {
  // run RAG/Generative Search query with a prompt to apply to each object returned by the near text query
  collection.query.fetchObjects().then(r=>{
    // print our objects
    console.log(JSON.stringify(r, null, 4));
    // update the first object
    collection.data.update({
        id: generateUuid5("belo horizonte"),
        properties: {
            location: null
        },
      }).then(r2=>{
        collection.query.fetchObjects().then(r3=>{
            // print all objects
            console.log(JSON.stringify(r3, null, 4));
        })
      })
  })
}

runFullExample();

Let me know if this helps :slight_smile: