AI 기반 요약

샘플 소스 코드 전체 보기

장소를 검색하여 AI 기반 요약을 확인하세요. 추천 검색어:

  • 동네 요약의 경우 '호텔'
  • EVCS 편의시설 요약의 경우 '전기자동차 충전소'
  • 장소 및 리뷰 요약의 경우 모든 음식점 또는 비즈니스

TypeScript

// Define DOM elements.
const mapElement = document.querySelector('gmp-map') as google.maps.MapElement;
const placeAutocomplete = document.querySelector(
    'gmp-place-autocomplete'
) as google.maps.places.PlaceAutocompleteElement;
const summaryPanel = document.getElementById('summary-panel') as HTMLDivElement;
const placeName = document.getElementById('place-name') as HTMLElement;
const placeAddress = document.getElementById('place-address') as HTMLElement;
const tabContainer = document.getElementById('tab-container') as HTMLDivElement;
const summaryContent = document.getElementById(
    'summary-content'
) as HTMLDivElement;
const aiDisclosure = document.getElementById('ai-disclosure') as HTMLDivElement;
const flagContentLink = document.getElementById('flag-content-link') as HTMLAnchorElement;

let innerMap;
let marker: google.maps.marker.AdvancedMarkerElement;

async function initMap(): Promise<void> {
    // Request needed libraries.
    const [] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('places'),
    ]);

    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
        streetViewControl: false,
        fullscreenControl: false,
    });

    // Bind autocomplete bounds to map bounds.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        placeAutocomplete.locationRestriction = innerMap.getBounds();
    });

    // Create the marker.
    marker = new google.maps.marker.AdvancedMarkerElement({
        map: innerMap,
    });

    // Handle selection of an autocomplete result.
    // prettier-ignore
    // @ts-ignore
    placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => {
            const place = placePrediction.toPlace();

            // Fetch all summary fields.
            await place.fetchFields({
                fields: [
                    'displayName',
                    'formattedAddress',
                    'location',
                    'generativeSummary',
                    'neighborhoodSummary',
                    'reviewSummary',
                    'evChargeAmenitySummary',
                ],
            });

            // Update the map viewport and position the marker.
            if (place.viewport) {
                innerMap.fitBounds(place.viewport);
            } else {
                innerMap.setCenter(place.location);
                innerMap.setZoom(17);
            }
            marker.position = place.location;

            // Update the panel UI.
            updateSummaryPanel(place);
        }
    );
}

function updateSummaryPanel(place: google.maps.places.Place) {
    // Reset UI
    summaryPanel.classList.remove('hidden');
    tabContainer.innerHTML = ''; // innerHTML is OK here since we're clearing known child elements.
    summaryContent.textContent = '';
    aiDisclosure.textContent = '';

    placeName.textContent = place.displayName || '';
    placeAddress.textContent = place.formattedAddress || '';

    let firstTabActivated = false;

    /**
     * Safe Helper: Accepts either a text string or a DOM Node (like a div or DocumentFragment).
     */
    const createTab = (
        label: string,
        content: string | Node,
        disclosure: string,
        flagUrl: string
    ) => {
        const btn = document.createElement('button');
        btn.className = 'tab-button';
        btn.textContent = label;

        btn.onclick = () => {
            // Do nothing if the tab is already active.
            if (btn.classList.contains('active')) {
                return;
            }

            // Manage the active class state.
            document
                .querySelectorAll('.tab-button')
                .forEach((b) => b.classList.remove('active'));
            btn.classList.add('active');

            if (typeof content === 'string') {
                summaryContent.textContent = content;
            } else {
                summaryContent.replaceChildren(content.cloneNode(true));
            }

            // Set the disclosure text.
            aiDisclosure.textContent = disclosure || 'AI-generated content.';

            // Add the content flag URI.
            if (flagUrl) {
                flagContentLink.href = flagUrl;
                flagContentLink.textContent = "Report an issue"
            }
        };

        tabContainer.appendChild(btn);

        // Auto-select the first available summary.
        if (!firstTabActivated) {
            btn.click();
            firstTabActivated = true;
        }
    };

    // --- 1. Generative Summary (Place) ---
    //@ts-ignore
    if (place.generativeSummary?.overview) {
        createTab(
            'Overview',
            //@ts-ignore
            place.generativeSummary.overview,
            //@ts-ignore
            place.generativeSummary.disclosureText,
            //@ts-ignore
            place.generativeSummary.flagContentURI
        );
    }

    // --- 2. Review Summary ---
    //@ts-ignore
    if (place.reviewSummary?.text) {
        createTab(
            'Reviews',
            //@ts-ignore
            place.reviewSummary.text,
            //@ts-ignore
            place.reviewSummary.disclosureText,
            //@ts-ignore
            place.reviewSummary.flagContentURI
        );
    }

    // --- 3. Neighborhood Summary ---
    //@ts-ignore
    if (place.neighborhoodSummary?.overview?.content) {
        createTab(
            'Neighborhood',
            //@ts-ignore
            place.neighborhoodSummary.overview.content,
            //@ts-ignore
            place.neighborhoodSummary.disclosureText,
            //@ts-ignore
            place.neighborhoodSummary.flagContentURI
        );
    }

    // --- 4. EV Amenity Summary (uses content blocks)) ---
    //@ts-ignore
    if (place.evChargeAmenitySummary) {
        //@ts-ignore
        const evSummary = place.evChargeAmenitySummary;
        const evContainer = document.createDocumentFragment();

        // Helper to build a safe DOM section for EV categories.
        const createSection = (title: string, text: string) => {
            const wrapper = document.createElement('div');
            wrapper.style.marginBottom = '15px'; // Or use a CSS class

            const titleEl = document.createElement('strong');
            titleEl.textContent = title;

            const textEl = document.createElement('div');
            textEl.textContent = text;

            wrapper.appendChild(titleEl);
            wrapper.appendChild(textEl);
            return wrapper;
        };

        // Check and append each potential section
        if (evSummary.overview?.content) {
            evContainer.appendChild(
                createSection('Overview', evSummary.overview.content)
            );
        }
        if (evSummary.coffee?.content) {
            evContainer.appendChild(
                createSection('Coffee', evSummary.coffee.content)
            );
        }
        if (evSummary.restaurant?.content) {
            evContainer.appendChild(
                createSection('Food', evSummary.restaurant.content)
            );
        }
        if (evSummary.store?.content) {
            evContainer.appendChild(
                createSection('Shopping', evSummary.store.content)
            );
        }

        // Only add the tab if the container has children
        if (evContainer.hasChildNodes()) {
            createTab(
                'EV Amenities',
                evContainer, // Passing a Node instead of string
                evSummary.disclosureText,
                evSummary.flagContentURI
            );
        }
    }

    // Safely handle the empty state.
    if (!firstTabActivated) {
        const msg = document.createElement('em');
        msg.textContent =
            'No AI summaries are available for this specific location.';
        summaryContent.replaceChildren(msg);
        aiDisclosure.textContent = '';
    }
}

initMap();

JavaScript

// Define DOM elements.
const mapElement = document.querySelector('gmp-map');
const placeAutocomplete = document.querySelector('gmp-place-autocomplete');
const summaryPanel = document.getElementById('summary-panel');
const placeName = document.getElementById('place-name');
const placeAddress = document.getElementById('place-address');
const tabContainer = document.getElementById('tab-container');
const summaryContent = document.getElementById('summary-content');
const aiDisclosure = document.getElementById('ai-disclosure');
const flagContentLink = document.getElementById('flag-content-link');
let innerMap;
let marker;
async function initMap() {
    // Request needed libraries.
    const [] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('places'),
    ]);
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
        streetViewControl: false,
        fullscreenControl: false,
    });
    // Bind autocomplete bounds to map bounds.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        placeAutocomplete.locationRestriction = innerMap.getBounds();
    });
    // Create the marker.
    marker = new google.maps.marker.AdvancedMarkerElement({
        map: innerMap,
    });
    // Handle selection of an autocomplete result.
    // prettier-ignore
    // @ts-ignore
    placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => {
        const place = placePrediction.toPlace();
        // Fetch all summary fields.
        await place.fetchFields({
            fields: [
                'displayName',
                'formattedAddress',
                'location',
                'generativeSummary',
                'neighborhoodSummary',
                'reviewSummary',
                'evChargeAmenitySummary',
            ],
        });
        // Update the map viewport and position the marker.
        if (place.viewport) {
            innerMap.fitBounds(place.viewport);
        }
        else {
            innerMap.setCenter(place.location);
            innerMap.setZoom(17);
        }
        marker.position = place.location;
        // Update the panel UI.
        updateSummaryPanel(place);
    });
}
function updateSummaryPanel(place) {
    // Reset UI
    summaryPanel.classList.remove('hidden');
    tabContainer.innerHTML = ''; // innerHTML is OK here since we're clearing known child elements.
    summaryContent.textContent = '';
    aiDisclosure.textContent = '';
    placeName.textContent = place.displayName || '';
    placeAddress.textContent = place.formattedAddress || '';
    let firstTabActivated = false;
    /**
     * Safe Helper: Accepts either a text string or a DOM Node (like a div or DocumentFragment).
     */
    const createTab = (label, content, disclosure, flagUrl) => {
        const btn = document.createElement('button');
        btn.className = 'tab-button';
        btn.textContent = label;
        btn.onclick = () => {
            // Do nothing if the tab is already active.
            if (btn.classList.contains('active')) {
                return;
            }
            // Manage the active class state.
            document
                .querySelectorAll('.tab-button')
                .forEach((b) => b.classList.remove('active'));
            btn.classList.add('active');
            if (typeof content === 'string') {
                summaryContent.textContent = content;
            }
            else {
                summaryContent.replaceChildren(content.cloneNode(true));
            }
            // Set the disclosure text.
            aiDisclosure.textContent = disclosure || 'AI-generated content.';
            // Add the content flag URI.
            if (flagUrl) {
                flagContentLink.href = flagUrl;
                flagContentLink.textContent = "Report an issue";
            }
        };
        tabContainer.appendChild(btn);
        // Auto-select the first available summary.
        if (!firstTabActivated) {
            btn.click();
            firstTabActivated = true;
        }
    };
    // --- 1. Generative Summary (Place) ---
    //@ts-ignore
    if (place.generativeSummary?.overview) {
        createTab('Overview', 
        //@ts-ignore
        place.generativeSummary.overview, 
        //@ts-ignore
        place.generativeSummary.disclosureText, 
        //@ts-ignore
        place.generativeSummary.flagContentURI);
    }
    // --- 2. Review Summary ---
    //@ts-ignore
    if (place.reviewSummary?.text) {
        createTab('Reviews', 
        //@ts-ignore
        place.reviewSummary.text, 
        //@ts-ignore
        place.reviewSummary.disclosureText, 
        //@ts-ignore
        place.reviewSummary.flagContentURI);
    }
    // --- 3. Neighborhood Summary ---
    //@ts-ignore
    if (place.neighborhoodSummary?.overview?.content) {
        createTab('Neighborhood', 
        //@ts-ignore
        place.neighborhoodSummary.overview.content, 
        //@ts-ignore
        place.neighborhoodSummary.disclosureText, 
        //@ts-ignore
        place.neighborhoodSummary.flagContentURI);
    }
    // --- 4. EV Amenity Summary (uses content blocks)) ---
    //@ts-ignore
    if (place.evChargeAmenitySummary) {
        //@ts-ignore
        const evSummary = place.evChargeAmenitySummary;
        const evContainer = document.createDocumentFragment();
        // Helper to build a safe DOM section for EV categories.
        const createSection = (title, text) => {
            const wrapper = document.createElement('div');
            wrapper.style.marginBottom = '15px'; // Or use a CSS class
            const titleEl = document.createElement('strong');
            titleEl.textContent = title;
            const textEl = document.createElement('div');
            textEl.textContent = text;
            wrapper.appendChild(titleEl);
            wrapper.appendChild(textEl);
            return wrapper;
        };
        // Check and append each potential section
        if (evSummary.overview?.content) {
            evContainer.appendChild(createSection('Overview', evSummary.overview.content));
        }
        if (evSummary.coffee?.content) {
            evContainer.appendChild(createSection('Coffee', evSummary.coffee.content));
        }
        if (evSummary.restaurant?.content) {
            evContainer.appendChild(createSection('Food', evSummary.restaurant.content));
        }
        if (evSummary.store?.content) {
            evContainer.appendChild(createSection('Shopping', evSummary.store.content));
        }
        // Only add the tab if the container has children
        if (evContainer.hasChildNodes()) {
            createTab('EV Amenities', evContainer, // Passing a Node instead of string
            evSummary.disclosureText, evSummary.flagContentURI);
        }
    }
    // Safely handle the empty state.
    if (!firstTabActivated) {
        const msg = document.createElement('em');
        msg.textContent =
            'No AI summaries are available for this specific location.';
        summaryContent.replaceChildren(msg);
        aiDisclosure.textContent = '';
    }
}
initMap();

CSS

/* Reuse existing map height */
gmp-map {
    height: 100%;
}

html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

/* Existing Autocomplete Card Style */
.place-autocomplete-card {
    background-color: #fff;
    border-radius: 5px;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    margin: 10px;
    padding: 15px;
    font-family: Roboto, sans-serif;
    font-size: 1rem;
}

gmp-place-autocomplete {
    width: 300px;
}

/* New: Summary Panel Styles */
.summary-card {
    background-color: #fff;
    border-radius: 5px;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    margin: 10px;
    padding: 0; /* Padding handled by children */
    font-family: Roboto, sans-serif;
    width: 350px;
    max-height: 80vh; /* Prevent overflow on small screens */
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.hidden {
    display: none;
}

#place-header {
    padding: 15px;
    background-color: #f8f9fa;
    border-bottom: 1px solid #ddd;
}

#place-header h2 {
    margin: 0 0 5px 0;
    font-size: 1.2rem;
}

#place-address {
    margin: 0;
    color: #555;
    font-size: 0.9rem;
}

/* Tab Navigation */
.tab-container {
    display: flex;
    border-bottom: 1px solid #ddd;
    background-color: #fff;
}

.tab-button {
    flex: 1;
    background: none;
    border: none;
    padding: 10px;
    cursor: pointer;
    font-weight: 500;
    color: #555;
    border-bottom: 3px solid transparent;
}

.tab-button:hover {
    background-color: #f1f1f1;
}

.tab-button.active {
    font-weight: bold;
    border-bottom: 3px solid #000000;
}

.tab-button.active:hover {
    background-color: #ffffff;
    cursor: default;
}

/* Content Area */
.content-area {
    padding: 15px;
    line-height: 1.5;
    font-size: 0.95rem;
    color: #333;
}

.disclosure-footer {
    font-size: 0.75rem;
    color: #666;
    padding: 10px 15px;
    border-top: 1px solid #eee;
    font-style: italic;
}

.flag-content-link {
    font-size: 0.75rem;
    color: #666;
    padding: 10px 15px;
    border-top: 1px solid #eee;
}
/* Reuse existing map height */
gmp-map {
    height: 100%;
}

html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

/* Existing Autocomplete Card Style */
.place-autocomplete-card {
    background-color: #fff;
    border-radius: 5px;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    margin: 10px;
    padding: 15px;
    font-family: Roboto, sans-serif;
    font-size: 1rem;
}

gmp-place-autocomplete {
    width: 300px;
}

/* New: Summary Panel Styles */
.summary-card {
    background-color: #fff;
    border-radius: 5px;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
    margin: 10px;
    padding: 0; /* Padding handled by children */
    font-family: Roboto, sans-serif;
    width: 350px;
    max-height: 80vh; /* Prevent overflow on small screens */
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.hidden {
    display: none;
}

#place-header {
    padding: 15px;
    background-color: #f8f9fa;
    border-bottom: 1px solid #ddd;
}

#place-header h2 {
    margin: 0 0 5px 0;
    font-size: 1.2rem;
}

#place-address {
    margin: 0;
    color: #555;
    font-size: 0.9rem;
}

/* Tab Navigation */
.tab-container {
    display: flex;
    border-bottom: 1px solid #ddd;
    background-color: #fff;
}

.tab-button {
    flex: 1;
    background: none;
    border: none;
    padding: 10px;
    cursor: pointer;
    font-weight: 500;
    color: #555;
    border-bottom: 3px solid transparent;
}

.tab-button:hover {
    background-color: #f1f1f1;
}

.tab-button.active {
    font-weight: bold;
    border-bottom: 3px solid #000000;
}

.tab-button.active:hover {
    background-color: #ffffff;
    cursor: default;
}

/* Content Area */
.content-area {
    padding: 15px;
    line-height: 1.5;
    font-size: 0.95rem;
    color: #333;
}

.disclosure-footer {
    font-size: 0.75rem;
    color: #666;
    padding: 10px 15px;
    border-top: 1px solid #eee;
    font-style: italic;
}

.flag-content-link {
    font-size: 0.75rem;
    color: #666;
    padding: 10px 15px;
}

HTML

<html>
    <head>
        <title>AI Place Summaries</title>
        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <!-- prettier-ignore -->
        <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
    </head>
    <body>
        <gmp-map center="37.805, -122.425" zoom="14" map-id="DEMO_MAP_ID">
            <!-- Search Input Card -->
            <div
                class="place-autocomplete-card"
                slot="control-inline-start-block-start">
                <p>Search for a place with AI summaries:</p>
                <gmp-place-autocomplete></gmp-place-autocomplete>
            </div>

            <!-- Summary text panel (initially hidden) -->
            <div
                id="summary-panel"
                class="summary-card hidden"
                slot="control-inline-end-block-start">
                <div id="place-header">
                    <h2 id="place-name"></h2>
                    <p id="place-address"></p>
                </div>

                <!-- Tabs for toggling summary types -->
                <div class="tab-container" id="tab-container"></div>

                <!-- Content display area -->
                <div id="summary-content" class="content-area"></div>

                <!-- Legal/AI Disclosure -->
                <div id="ai-disclosure" class="disclosure-footer"></div>

                <!-- Flag content link -->
                <a id="flag-content-link" class="flag-content-link"></a>
            </div>
        </gmp-map>
    </body>
</html>

샘플 사용해 보기

AI 기반 요약은 특정 장소, 장소 주변 지역, 장소와 관련된 리뷰에 관한 유용한 정보를 제공하는 장소 또는 지역의 개요입니다. AI 기반 요약에는 세 가지 유형이 있습니다.

  • 장소 요약: 특정 장소 ID에 특화된 간략한 100자 개요로, 다양한 유형의 데이터를 집계하여 장소의 개괄적인 스냅샷을 제공합니다.

  • 리뷰 요약: 사용자 리뷰만을 기반으로 생성된 장소 요약입니다.

  • 지역 요약: 장소 주변 지역에 대해 생성된 요약으로, 주변 관심 장소를 비롯한 추가 컨텍스트를 제공합니다. 영역 요약은 다음 두 가지 유형 중 하나일 수 있습니다.

    • 동네 요약: 유형이 premise, street_address이고 주택숙박 카테고리의 모든 유형인 장소의 근처 관심 장소에 관한 대략적인 개요입니다.

    • 전기 자동차 충전소 편의시설 요약: 유형이 electric_vehicle_charging_station인 장소의 근처 관심 장소에 대한 개략적인 개요입니다.

AI 기반 요약 가져오기

AI 기반 요약을 가져와 표시하려면 다음 단계를 따르세요.

  1. Places 라이브러리를 로드합니다.

    const { Place } = await google.maps.importLibrary("places");
  2. Place 인스턴스를 가져옵니다. 다음 스니펫은 장소 ID에서 Place 인스턴스를 만드는 방법을 보여줍니다.

    const place = new Place("ChIJaYaXFTqq3oARNy537Kb_W_c");
  3. place.fetchFields() 호출에서 사용할 요약 종류의 필드를 지정합니다. 다음 스니펫에서는 모든 요약 필드가 요청됩니다.

    await place.fetchFields({
      fields: [
        'generativeSummary',
        'neighborhoodSummary',
        'reviewSummary',
        'evChargeAmenitySummary'
        // Include other fields as needed.
      ]
    });
              
  4. 각각 generativeSummary, neighborhoodSummary, reviewSummary, evChargeAmenitySummary 속성에 액세스하여 요약 데이터를 가져옵니다. 다음 스니펫은 generativeSummary에서 개요를 가져오는 방법을 보여줍니다.

    const summaryText = place.generativeSummary.overview;
            

모든 장소에 AI 기반 요약이 있는 것은 아니므로 사용자에게 표시하기 전에 필요한 데이터가 있는지 확인하세요. 다음 스니펫은 if 문을 사용하여 generativeSummary를 확인합니다.

if (place.generativeSummary) {
  overviewText = place.generativeSummary.overview;
} else {
  overviewText = 'No summary is available.';
}
    

또는 nullish 연산자를 사용하여 요약의 존재 여부를 간결하게 확인할 수 있습니다.

const overviewText = place.generativeSummary.overview ?? 'No summary is available.';
    

필수 저작자 표시

앱에 표시되는 모든 AI 기반 요약에는 Google 정책 및 표준에 따라 적절한 저작자 표시가 포함되어야 합니다. 자세한 내용은 Maps JavaScript API 정책 및 저작자 표시를 참고하세요.

장소 요약

장소 요약은 특정 장소 ID에 대한 간략한 100자 개요로, 장소의 대략적인 스냅샷을 제공합니다. 장소 요약에서는 인기 음식, 서비스 또는 장소에서 구매할 수 있는 상품을 강조할 수 있습니다.

  • '캐주얼한 공간에서 푸짐한 전통 이탈리아 요리를 선보이는 Forum Shops 식당'

  • '컷, 염색, 블로우 드라이를 제공하는 세련된 미용실'

  • '다양한 빈티지 장식, 가구, 의류를 판매하는 여러 판매자가 있는 대형 매장'

장소 요약은 문화, 엔터테인먼트 및 레크리에이션, 음식 및 음료, 쇼핑, 서비스, 스포츠 카테고리의 지원되는 유형에 표시된 장소 유형에 사용할 수 있습니다.

장소 요약은 다음 언어와 지역의 관심 장소에 대해 지원됩니다.

언어 지역
영어

인도

미국

장소 요약 요청

생성형 장소 요약을 요청하려면 fetchFields()을 호출할 때 generativeSummary 필드를 포함하세요.

await place.fetchFields({
    fields: [
        'generativeSummary',
        // Include other fields as needed.
    ],
});
    

generativeSummary 속성을 사용하여 장소 요약을 가져옵니다. 다음 스니펫은 generativeSummary에서 개요 및 공개 텍스트를 가져옵니다.

if (place.generativeSummary) {
    console.log("Place Overview:", place.generativeSummary.overview);
    console.log("Disclosure:", place.generativeSummary.disclosureText);
}
    

리뷰 요약

리뷰 요약은 사용자 리뷰만을 기반으로 생성된 요약입니다. 리뷰 요약은 장소 속성, 리뷰 작성자 감정과 같은 사용자 리뷰의 주요 요소를 종합하여 개요 수준의 유용한 정보를 제공하고 사용자가 충분한 정보를 바탕으로 결정을 내릴 수 있도록 지원합니다.

예를 들어 샌프란시스코 페리 빌딩의 리뷰 요약에는 음식과 쇼핑부터 전망과 분위기에 이르기까지 다양한 정보가 포함됩니다.

'방문객들은 이 역사적인 명소에 다양한 상점, 레스토랑, 농산물 직판장이 있으며, 만과 도시의 전망이 훌륭하다고 말합니다. 또한 활기찬 분위기, 다른 목적지로 이동하기 편리한 페리, 지역 비즈니스를 즐길 수 있는 기회도 강조합니다."

다음 언어와 지역의 관심 장소에 대해 리뷰 요약이 지원됩니다.

언어 지역
영어 과테말라, 도미니카 공화국, 멕시코, 미국, 베네수엘라, 볼리비아, 브라질, 영국, 아르헨티나, 에콰도르, 우루과이, 인도, 일본, 칠레, 코스타리카, 콜롬비아, 파라과이, 페루
일본어 일본
포르투갈어 브라질
스페인어 과테말라, 도미니카 공화국, 멕시코, 미국, 베네수엘라, 볼리비아, 아르헨티나, 에콰도르, 우루과이, 칠레, 코스타리카, 콜롬비아, 파라과이, 페루

검토 요약 요청

검토 요약을 요청하려면 fetchFields() 호출 시 reviewSummary 필드를 포함하세요.

await place.fetchFields({
    fields: [
        'reviewSummary',
        // Include other fields as needed.
    ],
});
  

reviewSummary 속성을 사용하여 리뷰 요약을 가져옵니다. 리뷰 요약을 가져오려면 reviewSummary.text 속성에 액세스합니다. 다음 스니펫은 reviewSummary에서 텍스트를 가져옵니다.

if (place.reviewSummary) {
    console.log("Place Review Summary:", place.reviewSummary.text);
}
  

지역 요약

지역 요약은 장소 주변 지역에 대해 생성됩니다. 지역 요약은 사용자가 목적지에 도착한 후 어디로 가고 무엇을 할지 더 잘 파악할 수 있도록 주변 명소 등 위치에 관한 추가 맥락을 제공합니다. 예를 들어 새 도시를 방문할 때 호텔에 대해 생성된 동네 요약을 확인하여 주변 지역에 대해 자세히 알아볼 수 있습니다.

  • "샌프란시스코의 활기찬 이 지역은 노스 비치와 차이나타운이 혼합된 곳으로, 금융 지구의 북서쪽에 위치하며 문학적 명소, 독특한 문화적 명소, 다양한 식당이 있습니다. 유명한 곳으로는 상징적인 시티 라이츠 서점, 흥미로운 케이블카 박물관, 번화한 차이나타운 거리가 있습니다.'

전기 자동차 충전을 고려 중인 경우 전기 자동차 충전소에 대해 생성된 요약을 확인하여 주변 지역에 대해 자세히 알아볼 수 있습니다.

  • '이 지역에는 스타벅스, 스시 진, 세이프웨이 등 다양한 식당이 도보 9분 거리에 있습니다.'

영역 설명과 함께 응답에는 설명에 언급된 장소의 Place 인스턴스 목록도 포함됩니다. 이러한 Place 인스턴스에서 fetchFields()를 호출하여 각 장소의 세부정보를 요청하세요.

AI 기반 지역 요약에는 두 가지 유형이 있습니다.

  • 동네 요약: 유형이 premise, street_address이고 주택숙박 카테고리의 모든 유형인 장소의 근처 관심 장소에 관한 대략적인 개요입니다.

  • 전기 자동차 충전소 편의시설 요약: 유형이 electric_vehicle_charging_station인 장소의 근처 관심 장소에 대한 개략적인 개요입니다.

지역 요약은 다음 언어 및 지역의 관심분야에 대해 지원됩니다.

언어 지역
영어 미국

동네 요약 요청

premise, street_address 유형의 장소와 주택숙박 시설 카테고리의 모든 유형의 장소에 대해 동네 요약을 요청할 수 있습니다. 동네 요약을 요청하려면 fetchFields()를 호출할 때 neighborhoodSummary 필드를 포함하세요.

await place.fetchFields({
    fields: [
        'neighborhoodSummary',
        // Include other fields as needed.
    ],
});
  

neighborhoodSummary 속성을 사용하여 동네 요약을 가져옵니다. 동네 요약을 가져오려면 neighborhoodSummary.content 속성에 액세스하여 텍스트를 가져옵니다.

다음 스니펫은 neighborhoodSummary의 콘텐츠를 가져옵니다.

if (place.neighborhoodSummary) {
    console.log("Place Neighborhood Summary:", place.neighborhoodSummary.overview.content);
}
  

전기차 충전소 편의시설 요약 요청

electric_vehicle_charging_station 유형의 장소에 대한 전기 자동차 충전소 편의시설 요약을 요청할 수 있습니다. EVCS 편의시설 요약은 overview, coffee, restaurant, store의 네 가지 요약 유형을 제공하므로 데이터 구조는 각 요약을 포함하는 객체의 배열입니다. 전기 자동차 충전소 편의시설 요약을 요청하려면 fetchFields() 호출 시 evChargeAmenitySummary 필드를 포함하세요.

await place.fetchFields({
    fields: [
        'evChargeAmenitySummary',
        // Include other fields as needed.
    ],
});
  

evChargeAmenitySummary 속성을 사용하여 전기 자동차 충전소 편의시설 요약을 가져옵니다. 요약에서 텍스트를 가져오려면 evChargeAmenitySummary.overview, evChargeAmenitySummary.coffee, evChargeAmenitySummary.restaurant, evChargeAmenitySummary.store 속성의 content 속성에 액세스합니다.

다음 스니펫은 evChargeAmenitySummary의 콘텐츠를 가져옵니다.

// overview, coffee, restaurant, store.
if (place.evChargeAmenitySummary) {
    console.log("Place EVCS Amenity Summary:", place.evChargeAmenitySummary.overview.content);
    console.log("Coffee:", place.evChargeAmenitySummary.coffee.content);
    console.log("Restaurants:", place.evChargeAmenitySummary.restaurant.content);
    console.log("Stores:", place.evChargeAmenitySummary.store.content);
}