algoliasearch-client-java icon indicating copy to clipboard operation
algoliasearch-client-java copied to clipboard

partialUpdateObject remove some fields

Open CedricJezequel opened this issue 3 years ago • 5 comments

  • Algolia Client Version: 3.16.5
  • Language Version: JAVA

Description

We implemented a new agent which update existing items from an Algolia index and we observed that partialUpdateObject does not work as expected : some fields, not declared in attributesToRetrieved, are removed when saving an updated item.

Steps To Reproduce

  1. Having an Algolia index with data (ex: [objectID, title, text, url, source, date, subSource])
  2. Set attributesToRetrieved with back office configuration (ex: [objectID, title, text, url, source])
  3. Retrieve items from this index with more restrictions on attributesToRetrieved (ex: [objectID, title, text])
  4. Add a new field to item (ex: score)
  5. Save item with partialUpdateObject with only changed fields (ex:[objectID, title, score]) => Items saved only have [objectID,title,text, url, source, score] fields and no more [date, subSource] fields

CedricJezequel avatar Jul 26 '22 12:07 CedricJezequel

Hello @CedricJezequel,

I can not really repro your issue. Here is what I did:

const algoliasearch = require('algoliasearch');

// Use admin api key to set settings
const clientAdmin = algoliasearch('KECOEVPMGH', 'ADMIN_API_KEY');
const indexAdmin = clientAdmin.initIndex('repro');
await indexAdmin.setSettings({
    "attributesToRetrieve": [
      "title"
    ],
    "unretrievableAttributes": [
      "date"
    ],
}).wait();

// Use write api key that do not have rights to retrieve `date`
const client = algoliasearch('KECOEVPMGH', 'WRITE_API_KEY');
const index = client.initIndex('repro');

await index.saveObject({
 objectID: 'my-object',
 title: 'bar',
 date: 'monday'
}).wait();

const obj1 = await index.getObject('my-object');
console.log(obj1);
console.log('date should be undefined: %s', typeof obj1.date === 'undefined')

await index.partialUpdateObject({
 objectID: 'my-object',
 score: 1,
}).wait();

const obj2 = await index.getObject('my-object');
console.log(obj2);
console.log('date should be undefined: %s', typeof obj2.date === 'undefined')


// check with admin
const obj3 = await indexAdmin.getObject('my-object', {
attributesToRetrieve: "*"
});
console.log(obj3);
console.log('date should not be undefined: %s', typeof obj3.date !== 'undefined')
console.log('score should not be undefined: %s', typeof obj3.score !== 'undefined')

The output:

Object {title: "bar", objectID: "my-object"}
"date should be undefined: true"

Object {title: "bar", objectID: "my-object"}
"date should be undefined: true"

Object {title: "bar", date: "monday", score: 1, objectID: "my-object"}
"date should not be undefined: true"
"score should not be undefined: true"

As you can see the field date has been hidden but can still be retrieved at the end, even after a partialUpdateObject. And the score prop is still there too.

Maybe you have missed something or the last part => Items saved only have [objectID,title,text, url, source, score] fields and no more [date, subSource] fields was not checked correctly?

bodinsamuel avatar Jul 29 '22 13:07 bodinsamuel

Hello @bodinsamuel, In fact, we use JAVA framework and not JS. And for the value checking, we directly see in Algolia Back Office, to avoid using a possibly restricted API Key.

CedricJezequel avatar Aug 01 '22 06:08 CedricJezequel

Yeah I used JS for simplicity but it works the same way, there is no logic in the API clients that would explain your issue. Can you compare your code with the code I wrote? Did you wait() for tasks correctly?

bodinsamuel avatar Aug 01 '22 08:08 bodinsamuel

Yes, it's almost the same code, we just use browseFrom method to retrieve all datas needed to be updated, make a loop on it on save all with partialUpdateObjects method. As we do not use Async method available on JAVA framework, no wait has been put :

val updates = mutableListOf()
articleIndex.browseObjects(query).forEach { tag ->
    run {
        val correctTitle = tag.title.replace(Regex(" \(.*\)"), "").trim()
        tag.pagesVues = getNbPagesVues(correctTitle)
        updates.add(tag)
        i++
        logger.info("{} tags processed", i)
    }
}

if (updates.isNotEmpty()) {
    articleIndex.partialUpdateObjects(updates)
}

CedricJezequel avatar Aug 01 '22 12:08 CedricJezequel

Okay I see, nothing seems incorrect here. About the wait I meant waitTask, indexing operation are asynchronous even if not reflected in the client https://www.algolia.com/doc/api-reference/api-methods/wait-task/?client=java

The last thing that could be explaining this: In the Algolia Back Office the person checking as all the permissions? The hidden fields are in the "Show more attributes" Screenshot 2022-08-01 at 15 26 29

If all correct then I'll reach out the Indexing team, as I don't have any more clue.

bodinsamuel avatar Aug 01 '22 13:08 bodinsamuel